win32-captureie 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +26 -0
- data/Manifest.txt +8 -1
- data/README.txt +28 -1
- data/TODO.txt +7 -4
- data/bin/prtie +3 -0
- data/config/hoe.rb +7 -6
- data/examples/capture-ruby-lang.rb +23 -0
- data/examples/each_ie.rb +28 -0
- data/examples/hilight-id.rb +47 -0
- data/lib/win32/capture_ie.rb +78 -9
- data/lib/win32/capture_ie/area.rb +56 -0
- data/lib/win32/capture_ie/bitmap.rb +66 -4
- data/lib/win32/capture_ie/browser.rb +194 -9
- data/lib/win32/capture_ie/cli/prt_ie.rb +6 -0
- data/lib/win32/capture_ie/commands/prt_ie.rb +3 -7
- data/lib/win32/capture_ie/feature.rb +63 -0
- data/lib/win32/capture_ie/screen_captor.rb +58 -45
- data/lib/win32/capture_ie/util.rb +45 -0
- data/lib/win32/capture_ie/version.rb +1 -1
- data/spec/dsl/behaviour_eval.rb +5 -0
- data/spec/spec.opts +0 -1
- data/spec/spec_helper.rb +8 -7
- data/spec/win32/capture_ie/area_spec.rb +19 -0
- data/spec/win32/capture_ie_spec.rb +0 -11
- data/tasks/deployment.rake +1 -1
- data/tasks/deployment2.rake +2 -1
- metadata +10 -3
- data/tasks/website.rake +0 -17
data/History.txt
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
== 0.2.0 / 2007-12-09
|
2
|
+
|
3
|
+
* Win32::CaptureIE.each
|
4
|
+
* Enumerate existing IE window.
|
5
|
+
|
6
|
+
* Capture web page as BLOB.
|
7
|
+
* Win32::CaptureIE::Browser#capture_browser_image
|
8
|
+
* Win32::CaptureIE::Browser#capture_page_image
|
9
|
+
* Win32::CaptureIE::Browser#capture_elements_image
|
10
|
+
|
11
|
+
* Support capture DOM elements.
|
12
|
+
* Win32::CaptureIE::Browser#capture_elements:
|
13
|
+
* CaptureIE specified DOM elements.
|
14
|
+
|
15
|
+
* Support RMagick.
|
16
|
+
* Win32::CaptureIE::Browser#capture_page:
|
17
|
+
* Converts the bitmap image to the format specified by the filename if RMagick available.
|
18
|
+
* If filename has ".bmp" extension, RMagick are optional.
|
19
|
+
* Win32::CaptureIE::Browser#capture_browser:
|
20
|
+
* ditto.
|
21
|
+
* Win32::CaptureIE.rmagick_available?
|
22
|
+
* Win32::CaptureIE.rmagick_enable?
|
23
|
+
* Win32::CaptureIE.enable_rmagick
|
24
|
+
* Win32::CaptureIE.disable_rmagick
|
25
|
+
|
26
|
+
|
1
27
|
== 0.1.0 / 2007-11-23
|
2
28
|
|
3
29
|
* Initial release
|
data/Manifest.txt
CHANGED
@@ -7,7 +7,11 @@ TODO.txt
|
|
7
7
|
bin/prtie
|
8
8
|
config/hoe.rb
|
9
9
|
config/requirements.rb
|
10
|
+
examples/capture-ruby-lang.rb
|
11
|
+
examples/each_ie.rb
|
12
|
+
examples/hilight-id.rb
|
10
13
|
lib/win32/capture_ie.rb
|
14
|
+
lib/win32/capture_ie/area.rb
|
11
15
|
lib/win32/capture_ie/base.rb
|
12
16
|
lib/win32/capture_ie/bitmap.rb
|
13
17
|
lib/win32/capture_ie/browser.rb
|
@@ -15,12 +19,14 @@ lib/win32/capture_ie/cli/base.rb
|
|
15
19
|
lib/win32/capture_ie/cli/prt_ie.rb
|
16
20
|
lib/win32/capture_ie/commands/base.rb
|
17
21
|
lib/win32/capture_ie/commands/prt_ie.rb
|
22
|
+
lib/win32/capture_ie/feature.rb
|
18
23
|
lib/win32/capture_ie/ffi.rb
|
19
24
|
lib/win32/capture_ie/ffi/base.rb
|
20
25
|
lib/win32/capture_ie/ffi/gdi32.rb
|
21
26
|
lib/win32/capture_ie/ffi/struct.rb
|
22
27
|
lib/win32/capture_ie/ffi/user32.rb
|
23
28
|
lib/win32/capture_ie/screen_captor.rb
|
29
|
+
lib/win32/capture_ie/util.rb
|
24
30
|
lib/win32/capture_ie/version.rb
|
25
31
|
lib/win32/capture_ie/window.rb
|
26
32
|
script/destroy
|
@@ -31,8 +37,10 @@ script/rdoc_filter.rb
|
|
31
37
|
script/txt2html
|
32
38
|
script/txt2html.cmd
|
33
39
|
setup.rb
|
40
|
+
spec/dsl/behaviour_eval.rb
|
34
41
|
spec/spec.opts
|
35
42
|
spec/spec_helper.rb
|
43
|
+
spec/win32/capture_ie/area_spec.rb
|
36
44
|
spec/win32/capture_ie_spec.rb
|
37
45
|
tasks/deployment.rake
|
38
46
|
tasks/deployment2.rake
|
@@ -42,4 +50,3 @@ tasks/helper/rake.rb
|
|
42
50
|
tasks/helper/rake_sh_filter.rb
|
43
51
|
tasks/helper/util.rb
|
44
52
|
tasks/rspec.rake
|
45
|
-
tasks/website.rake
|
data/README.txt
CHANGED
@@ -6,9 +6,29 @@
|
|
6
6
|
require "win32/capture_ie"
|
7
7
|
|
8
8
|
Win32::CaptureIE.start("http://www.ruby-lang.org/") do |ie|
|
9
|
-
ie.capture_page("ruby-lang-whole-page.bmp")
|
10
9
|
ie.capture_browser("ruby-lang-browser.bmp")
|
11
10
|
ie.capture_browser("ruby-lang-onepage.bmp", :only_drawing_area => true)
|
11
|
+
open("ruby-lang-wholepage.bmp", "wb") do |w|
|
12
|
+
ie.capture_page(w)
|
13
|
+
end
|
14
|
+
|
15
|
+
# require RMagick
|
16
|
+
ie.capture_page($stdout, :format => "jpg")
|
17
|
+
ie.capture_browser("ruby-lang-browser.png")
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
require "cgi"
|
22
|
+
Win32::CaptureIE.each do |ie|
|
23
|
+
url = ie.document.location.href
|
24
|
+
ie.capture_page("#{CGI.escape(url)}.png") do |image|
|
25
|
+
gc = Magick::Draw.new
|
26
|
+
gc.stroke = "white"
|
27
|
+
gc.text_undercolor("blue")
|
28
|
+
gc.text(5, ie.body_area.height - 5, url)
|
29
|
+
gc.draw(image)
|
30
|
+
image
|
31
|
+
end
|
12
32
|
end
|
13
33
|
|
14
34
|
|
@@ -24,6 +44,13 @@ For more details, please see {prtie}[link:files/bin/prtie.html] document.
|
|
24
44
|
gem install win32-captureie
|
25
45
|
|
26
46
|
|
47
|
+
=== REQUIREMENTS
|
48
|
+
|
49
|
+
* Internet Explorer
|
50
|
+
* win32ole (standard library)
|
51
|
+
* RMagick[http://rubyforge.org/projects/rmagick] (optional)
|
52
|
+
|
53
|
+
|
27
54
|
=== ACKNOWLEDGMENTS
|
28
55
|
|
29
56
|
Thanks to P.Smejkal author for his Perl's <tt>Win32-CaptureIE</tt>,
|
data/TODO.txt
CHANGED
@@ -2,11 +2,15 @@
|
|
2
2
|
|
3
3
|
=== lib
|
4
4
|
|
5
|
-
* RMagick
|
6
|
-
* png, jpg, ...
|
7
|
-
* capture_element
|
8
5
|
* capture_page(1)
|
6
|
+
* rcairo
|
7
|
+
* frame
|
9
8
|
* filter, effect
|
9
|
+
* xxx_image block
|
10
|
+
* animation gif
|
11
|
+
* offline mode
|
12
|
+
* font size / page encoding
|
13
|
+
|
10
14
|
|
11
15
|
=== bin/capture-ie
|
12
16
|
|
@@ -15,7 +19,6 @@
|
|
15
19
|
|
16
20
|
Usage: capture-ie [options ...] URL [ [options ...] URL ]...
|
17
21
|
|
18
|
-
-T, --type
|
19
22
|
-o, --output
|
20
23
|
--stdout
|
21
24
|
-N --worker=1
|
data/bin/prtie
CHANGED
@@ -24,6 +24,9 @@
|
|
24
24
|
# -w, --wait=SECONDS wait SECONDS between retrievals
|
25
25
|
# -d, --output-directory=DIRECTORY save capture to DIRECTORY/...
|
26
26
|
# -o, --output=FILE save capture to FILE
|
27
|
+
# -T, --output-type=TYPE save capture as image TYPE
|
28
|
+
# Default: PNG (RMagick available)
|
29
|
+
# or BMP (not available)
|
27
30
|
# -D, --output-digest=ALGORITHM use output filename as hex-encoded version
|
28
31
|
# of a given URL
|
29
32
|
# ALGORITHM: MD5, SHA1, SHA512 ...
|
data/config/hoe.rb
CHANGED
@@ -48,7 +48,7 @@ end
|
|
48
48
|
|
49
49
|
# Generate all the Rake tasks
|
50
50
|
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
51
|
-
|
51
|
+
HOE = Hoe.new(GEM_NAME, VERS) do |p|
|
52
52
|
p.author = AUTHOR
|
53
53
|
p.description = DESCRIPTION
|
54
54
|
p.email = EMAIL
|
@@ -61,12 +61,13 @@ hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
|
61
61
|
# == Optional
|
62
62
|
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
63
63
|
#p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
|
64
|
-
|
65
64
|
#p.spec_extras = {} # A hash of extra values to set in the gemspec.
|
66
|
-
|
65
|
+
|
66
|
+
p.need_zip = true
|
67
|
+
p.need_tar = false
|
67
68
|
end
|
68
69
|
|
69
|
-
CHANGES =
|
70
|
+
CHANGES = HOE.paragraphs_of('History.txt', 0..1).join("\n\n")
|
70
71
|
PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
|
71
|
-
|
72
|
-
|
72
|
+
HOE.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
|
73
|
+
HOE.rsync_args = '-av --delete --ignore-errors'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "pathname"
|
3
|
+
|
4
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), "../lib")
|
5
|
+
require "win32/capture_ie"
|
6
|
+
|
7
|
+
|
8
|
+
outdir = Pathname.new(__FILE__).basename(".*")
|
9
|
+
FileUtils.mkdir_p(outdir)
|
10
|
+
|
11
|
+
Win32::CaptureIE.start("http://www.ruby-lang.org/") do |ie|
|
12
|
+
ie.capture_browser(outdir + "ruby-lang-browser.bmp")
|
13
|
+
ie.capture_browser(outdir + "ruby-lang-onepage.bmp", :only_drawing_area => true)
|
14
|
+
open(outdir + "ruby-lang-wholepage.bmp", "wb") do |w|
|
15
|
+
ie.capture_page(w)
|
16
|
+
end
|
17
|
+
|
18
|
+
# require RMagick
|
19
|
+
ie.capture_browser(outdir + "ruby-lang-browser.png")
|
20
|
+
open(outdir + "ruby-lang-wholepage.png", "wb") do |w|
|
21
|
+
ie.capture_page(w, :format => "png")
|
22
|
+
end
|
23
|
+
end
|
data/examples/each_ie.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "digest/md5"
|
2
|
+
require "fileutils"
|
3
|
+
require "pathname"
|
4
|
+
require "time"
|
5
|
+
|
6
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), "../lib")
|
7
|
+
require "win32/capture_ie"
|
8
|
+
|
9
|
+
outdir = Pathname.new(__FILE__).basename(".*")
|
10
|
+
FileUtils.mkdir_p(outdir)
|
11
|
+
|
12
|
+
Win32::CaptureIE.reject {|ie| ie.load_error? }.each do |ie|
|
13
|
+
url = ie.document.location.href
|
14
|
+
digest = Digest::MD5.hexdigest(url)
|
15
|
+
output = outdir + "#{digest}.png"
|
16
|
+
|
17
|
+
puts url
|
18
|
+
text = "#{url} - #{Time.now.iso8601}"
|
19
|
+
ie.capture_page(output) do |image|
|
20
|
+
gc = Magick::Draw.new
|
21
|
+
gc.stroke = "white"
|
22
|
+
gc.text_undercolor("blue")
|
23
|
+
gc.text(5, ie.body_area.height - 5, text)
|
24
|
+
gc.draw(image)
|
25
|
+
image
|
26
|
+
end
|
27
|
+
puts " => #{output}"
|
28
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "digest/md5"
|
2
|
+
require "fileutils"
|
3
|
+
require "pathname"
|
4
|
+
require "time"
|
5
|
+
|
6
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), "../lib")
|
7
|
+
require "win32/capture_ie"
|
8
|
+
|
9
|
+
if ARGV.size < 2
|
10
|
+
$stderr.puts "Usage: #{$0} URL ID..."
|
11
|
+
exit 2
|
12
|
+
end
|
13
|
+
|
14
|
+
uri = ARGV.shift
|
15
|
+
hilight_ids = ARGV
|
16
|
+
colors = %w(red green blue)
|
17
|
+
|
18
|
+
outdir = Pathname.new(__FILE__).basename(".*")
|
19
|
+
digest = Digest::MD5.hexdigest(uri)
|
20
|
+
output = outdir + "#{digest}.png"
|
21
|
+
FileUtils.mkdir_p(outdir)
|
22
|
+
|
23
|
+
FileUtils.mkdir_p(File.dirname(output))
|
24
|
+
Win32::CaptureIE.start(uri) do |b|
|
25
|
+
b.capture_page(output) do |image|
|
26
|
+
hilight_ids.each_with_index do |id, i|
|
27
|
+
color = colors[i % colors.length]
|
28
|
+
area = b.abs_element_area(id)
|
29
|
+
gc = Magick::Draw.new
|
30
|
+
gc.stroke = color
|
31
|
+
gc.fill = color
|
32
|
+
gc.stroke_width = 4
|
33
|
+
gc.stroke_opacity(0.5)
|
34
|
+
gc.fill_opacity(0.2)
|
35
|
+
gc.rectangle(*area.rect)
|
36
|
+
gc.draw(image)
|
37
|
+
|
38
|
+
gc = Magick::Draw.new
|
39
|
+
gc.stroke_width = 1
|
40
|
+
gc.stroke = "white"
|
41
|
+
gc.text_undercolor(color)
|
42
|
+
gc.text(area.x1, area.y1 + 10, id)
|
43
|
+
gc.draw(image)
|
44
|
+
end
|
45
|
+
image
|
46
|
+
end
|
47
|
+
end
|
data/lib/win32/capture_ie.rb
CHANGED
@@ -1,13 +1,75 @@
|
|
1
1
|
require "win32ole"
|
2
|
+
|
3
|
+
require "win32/capture_ie/feature"
|
2
4
|
require "win32/capture_ie/browser"
|
3
5
|
require "win32/capture_ie/version"
|
4
6
|
|
7
|
+
|
5
8
|
module Win32 #:nodoc:
|
6
9
|
|
10
|
+
#
|
11
|
+
# Ex)
|
12
|
+
#
|
13
|
+
# require "rubygems"
|
14
|
+
# require "win32/capture_ie"
|
15
|
+
#
|
16
|
+
# Win32::CaptureIE.start do |ie|
|
17
|
+
# ie.navigate("http://www.ruby-lang.org/")
|
18
|
+
# ie.capture_browser("ruby-lang.bmp")
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# ie = Win32::CaptureIE.start
|
22
|
+
# begin
|
23
|
+
# ie.navigate("http://rubyforge.org/")
|
24
|
+
# ie.capture_browser("rubyforge.bmp")
|
25
|
+
# ensure
|
26
|
+
# ie.quit
|
27
|
+
# end
|
28
|
+
#
|
7
29
|
module CaptureIE
|
30
|
+
# see Win32::CaptureIE#connect
|
31
|
+
class ConnectError < StandardError; end
|
32
|
+
|
8
33
|
class <<self
|
34
|
+
include Enumerable
|
35
|
+
include Win32::CaptureIE::Feature
|
36
|
+
|
37
|
+
# Do not load/use RMagick even if RMagick is installed.
|
38
|
+
#
|
39
|
+
# Win32::CaptureIE.connect_or_start(url) do |b|
|
40
|
+
# Win32::CaptureIE.disable_rmagick
|
41
|
+
# b.capture_browser("foo.png") #=> Win32::CaptureIE::Feature::DisabledError
|
42
|
+
# b.capture_browser("foo.bmp") #=> ok
|
43
|
+
# Win32::CaptureIE.enable_rmagick
|
44
|
+
# b.capture_browser("foo.png") #=> ok and load RMagick automatically.
|
45
|
+
# Win32::CaptureIE.disable_rmagick
|
46
|
+
# b.capture_browser("foo.png") #=> Win32::CaptureIE::Feature::DisabledError
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
def disable_rmagick
|
50
|
+
disable_feature("RMagick")
|
51
|
+
end
|
9
52
|
|
10
|
-
|
53
|
+
# enable RMagick.
|
54
|
+
#
|
55
|
+
# see disable_rmagick for more details.
|
56
|
+
def enable_rmagick
|
57
|
+
enable_feature("RMagick")
|
58
|
+
end
|
59
|
+
|
60
|
+
# RMagick is enabled?
|
61
|
+
#
|
62
|
+
# see disable_rmagick for more details.
|
63
|
+
def rmagick_enable?
|
64
|
+
feature_enable?("RMagick")
|
65
|
+
end
|
66
|
+
|
67
|
+
# RMagick is installed and enabled?
|
68
|
+
#
|
69
|
+
# This method will load RMagick (and rubygems) automatically.
|
70
|
+
def rmagick_available?
|
71
|
+
feature_available?("RMagick")
|
72
|
+
end
|
11
73
|
|
12
74
|
# call-seq:
|
13
75
|
# start(url) -> Win32::CaptureIE::Browser
|
@@ -45,9 +107,16 @@ module Win32 #:nodoc:
|
|
45
107
|
attach(url, lambda { raise ConnectError, "no such IE `#{url}'" }, opts, &block)
|
46
108
|
end
|
47
109
|
|
110
|
+
# Calls +block+ for each IE window,
|
111
|
+
# passing Win32::CaptureIE::Browser object to the supplied +block+.
|
112
|
+
def each
|
113
|
+
each_ie {|ie| yield wrap(ie) }
|
114
|
+
end
|
115
|
+
|
116
|
+
|
48
117
|
def attach(url, fallback, opts=nil, &block)
|
49
118
|
url = url.to_s
|
50
|
-
ie =
|
119
|
+
ie = each_ie {|ie| break ie if ie.LocationURL == url }
|
51
120
|
if ie
|
52
121
|
run(wrap(ie), opts, &block)
|
53
122
|
else
|
@@ -56,11 +125,14 @@ module Win32 #:nodoc:
|
|
56
125
|
end
|
57
126
|
private :attach
|
58
127
|
|
59
|
-
def
|
128
|
+
def each_ie
|
60
129
|
shell = WIN32OLE.new("Shell.Application")
|
61
|
-
w = shell.Windows
|
62
|
-
w.
|
130
|
+
w = shell.Windows
|
131
|
+
w.each do |ie|
|
132
|
+
yield ie if ie.FullName =~ /\biexplore\.exe\z/i
|
133
|
+
end
|
63
134
|
end
|
135
|
+
private :each_ie
|
64
136
|
|
65
137
|
def run(ie, opts=nil, &block)
|
66
138
|
opts ||= {}
|
@@ -68,10 +140,7 @@ module Win32 #:nodoc:
|
|
68
140
|
begin
|
69
141
|
block.call(ie)
|
70
142
|
ensure
|
71
|
-
|
72
|
-
ie.browser.Quit unless opts[:no_quit]
|
73
|
-
rescue WIN32OLERuntimeError => ignored
|
74
|
-
end
|
143
|
+
ie.quit unless opts[:no_quit]
|
75
144
|
end
|
76
145
|
end
|
77
146
|
private :run
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "win32/capture_ie/base"
|
2
|
+
|
3
|
+
module Win32::CaptureIE
|
4
|
+
|
5
|
+
class Area #:nodoc:
|
6
|
+
|
7
|
+
attr_accessor :x, :y, :w, :h
|
8
|
+
alias x1 x
|
9
|
+
alias y1 y
|
10
|
+
alias width w
|
11
|
+
alias height h
|
12
|
+
|
13
|
+
def initialize(x, y, w, h)
|
14
|
+
@x, @y, @w, @h = x, y, w, h
|
15
|
+
end
|
16
|
+
|
17
|
+
def x2
|
18
|
+
x + w
|
19
|
+
end
|
20
|
+
|
21
|
+
def y2
|
22
|
+
y + h
|
23
|
+
end
|
24
|
+
|
25
|
+
def top_left
|
26
|
+
[x1, y1]
|
27
|
+
end
|
28
|
+
|
29
|
+
def top_right
|
30
|
+
[x2, y1]
|
31
|
+
end
|
32
|
+
|
33
|
+
def bottom_left
|
34
|
+
[x1, y2]
|
35
|
+
end
|
36
|
+
|
37
|
+
def bottom_right
|
38
|
+
[x2, y2]
|
39
|
+
end
|
40
|
+
|
41
|
+
def rect
|
42
|
+
[x1, y1, x2, y2]
|
43
|
+
end
|
44
|
+
|
45
|
+
def +(other)
|
46
|
+
tl = top_left.zip(other.top_left).map{|e| e.min }
|
47
|
+
br = bottom_right.zip(other.bottom_right).map{|e| e.max }
|
48
|
+
self.class.new(tl[0], tl[1], br[0] - tl[0], br[1] - tl[1])
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_s
|
52
|
+
"[(%d, %d), (%d, %d)]" % rect
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require "win32/capture_ie/base"
|
2
|
+
require "win32/capture_ie/util"
|
3
|
+
require "win32/capture_ie/feature"
|
2
4
|
require "win32/capture_ie/ffi"
|
3
5
|
|
6
|
+
|
4
7
|
module Win32::CaptureIE
|
5
8
|
|
6
9
|
class BitMapSizeError < StandardError #:nodoc:
|
@@ -8,6 +11,8 @@ module Win32::CaptureIE
|
|
8
11
|
|
9
12
|
class BitMap #:nodoc:
|
10
13
|
include Win32::CaptureIE::FFI::GDI32
|
14
|
+
include Win32::CaptureIE::Util
|
15
|
+
include Win32::CaptureIE::Feature
|
11
16
|
|
12
17
|
attr_reader :width, :height
|
13
18
|
def initialize(width, height)
|
@@ -89,16 +94,60 @@ module Win32::CaptureIE
|
|
89
94
|
end
|
90
95
|
alias info create_bitmapinfo
|
91
96
|
|
92
|
-
def save(
|
93
|
-
|
94
|
-
|
97
|
+
def save(writable, format=nil, &rmagick_filter)
|
98
|
+
format ||= guess_format(writable)
|
99
|
+
begin
|
100
|
+
load_depended_library("RMagick", "save `#{format}' format")
|
101
|
+
save_magick(writable, format, &rmagick_filter)
|
102
|
+
rescue DisabledError, LoadError => e
|
103
|
+
raise e unless format == "bmp"
|
104
|
+
if rmagick_filter and $VERBOSE
|
105
|
+
at = eval("[__FILE__, __LINE__]", rmagick_filter.binding)
|
106
|
+
warn "Ignore block argument at %s:%d because RMagick is not available." % at
|
107
|
+
end
|
108
|
+
save_bmp(writable)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def save_magick(writable, format, &rmagick_filter)
|
113
|
+
img = to_magick(format)
|
114
|
+
img = run_filter(img, rmagick_filter) if rmagick_filter
|
115
|
+
with_output_stream(writable) do |w|
|
116
|
+
w.write img.to_blob
|
117
|
+
end
|
118
|
+
nil
|
119
|
+
end
|
120
|
+
private :save_magick
|
121
|
+
|
122
|
+
def save_bmp(writable)
|
123
|
+
with_output_stream(writable) do |w|
|
124
|
+
to_blob {|data|
|
95
125
|
w.write data
|
96
126
|
}
|
97
127
|
end
|
98
128
|
nil
|
99
129
|
end
|
130
|
+
private :save_bmp
|
131
|
+
|
132
|
+
def to_image(format=nil)
|
133
|
+
format ||= "bmp"
|
134
|
+
begin
|
135
|
+
to_magick(format)
|
136
|
+
rescue DisabledError, LoadError => e
|
137
|
+
raise e unless format == "bmp"
|
138
|
+
to_blob
|
139
|
+
end
|
140
|
+
end
|
100
141
|
|
101
|
-
def
|
142
|
+
def to_magick(format=nil)
|
143
|
+
load_depended_library("RMagick", "create Magick::ImageList")
|
144
|
+
r = Magick::ImageList.new.from_blob(to_blob)
|
145
|
+
r.format = format if format
|
146
|
+
r
|
147
|
+
end
|
148
|
+
private :to_magick
|
149
|
+
|
150
|
+
def to_blob(&block)
|
102
151
|
v = [create_bitmapfileheader.pack, create_bitmapinfo.bmiHeader.pack, @data]
|
103
152
|
if block
|
104
153
|
v.each(&block)
|
@@ -106,6 +155,19 @@ module Win32::CaptureIE
|
|
106
155
|
v.join
|
107
156
|
end
|
108
157
|
end
|
158
|
+
private :to_blob
|
159
|
+
|
160
|
+
def run_filter(image, *filters)
|
161
|
+
filters.inject(image){|image,filter|
|
162
|
+
r = filter.call(image) || image
|
163
|
+
if not [Magick::ImageList, Magick::Image].any?{|k| k === r }
|
164
|
+
raise ArgumentError, "filter `#{filter.inspect}' should return " +
|
165
|
+
"Magick::ImageList, Magick::Image or nil. but was `#{r.inspect}' (#{r.class})."
|
166
|
+
end
|
167
|
+
r
|
168
|
+
}
|
169
|
+
end
|
170
|
+
private :run_filter
|
109
171
|
|
110
172
|
def inspect
|
111
173
|
"#<%s:0x%x @width=%d @height=%d @data=...>" % [self.class, self.object_id << 1, @height, @width]
|
@@ -1,8 +1,10 @@
|
|
1
1
|
require "win32/capture_ie/base"
|
2
2
|
require "win32/capture_ie/ffi"
|
3
3
|
require "win32/capture_ie/window"
|
4
|
+
require "win32/capture_ie/area"
|
4
5
|
require "win32/capture_ie/screen_captor"
|
5
6
|
|
7
|
+
|
6
8
|
module Win32::CaptureIE
|
7
9
|
class Browser < Window
|
8
10
|
module ReadyState
|
@@ -30,6 +32,14 @@ module Win32::CaptureIE
|
|
30
32
|
@embedding_ie_hwnd = nil
|
31
33
|
end
|
32
34
|
|
35
|
+
def quit(ignore_error = true)
|
36
|
+
begin
|
37
|
+
browser.Quit
|
38
|
+
rescue WIN32OLERuntimeError => e
|
39
|
+
raise e unless ignore_error
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
33
43
|
def document
|
34
44
|
@document ||= browser.document rescue nil if browser
|
35
45
|
end
|
@@ -51,6 +61,46 @@ module Win32::CaptureIE
|
|
51
61
|
end
|
52
62
|
private :body0
|
53
63
|
|
64
|
+
def body_area
|
65
|
+
Area.new(0, 0, body.scrollWidth, body.scrollHeight) if body
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_element(id, parent=document)
|
69
|
+
r = parent.getElementById(id)
|
70
|
+
raise ArgumentError, "unknown element `##{id}'" unless r
|
71
|
+
r
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_element(id_or_element)
|
75
|
+
case id_or_element
|
76
|
+
when WIN32OLE
|
77
|
+
id_or_element
|
78
|
+
when String
|
79
|
+
get_element(id_or_element)
|
80
|
+
else
|
81
|
+
raise ArgumentError, "Invalid argument #{id_or_element.inspect}:#{id_or_element.class}," +
|
82
|
+
" expected String or WIN32OLE."
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def abs_element_area(id_or_element)
|
87
|
+
# Let's calculate the absolute position of the object on the page
|
88
|
+
elem = to_element(id_or_element)
|
89
|
+
x = y = 0
|
90
|
+
p = elem
|
91
|
+
while p
|
92
|
+
x += p.offsetLeft
|
93
|
+
y += p.offsetTop
|
94
|
+
p = p.offsetParent
|
95
|
+
end
|
96
|
+
|
97
|
+
# This is the size of the object including its border
|
98
|
+
w = elem.offsetWidth
|
99
|
+
h = elem.offsetHeight
|
100
|
+
|
101
|
+
Area.new(x, y, w, h)
|
102
|
+
end
|
103
|
+
|
54
104
|
def compatible_mode?
|
55
105
|
v = document.compatMode rescue nil
|
56
106
|
return (v.nil? or v == "BackCompat")
|
@@ -79,28 +129,163 @@ module Win32::CaptureIE
|
|
79
129
|
end
|
80
130
|
private :find_embedding_ie_hwnd
|
81
131
|
|
132
|
+
# save window scroll position.
|
82
133
|
def save_excursion
|
83
134
|
top, left = body.scrollTop, body.scrollLeft
|
84
135
|
begin
|
85
136
|
yield
|
86
137
|
ensure
|
87
|
-
|
138
|
+
begin
|
139
|
+
body.scrollTop, body.scrollLeft = top, left
|
140
|
+
rescue => ignored
|
141
|
+
end
|
88
142
|
end
|
89
143
|
end
|
90
144
|
|
91
145
|
# call-seq:
|
92
|
-
# capture_browser(
|
93
|
-
# capture_browser(
|
146
|
+
# capture_browser(writable, :format => "bmp")
|
147
|
+
# capture_browser(writable, :format => "bmp", :only_drawing_area => true)
|
148
|
+
# capture_browser(writable, :format => "bmp") {|image| ... }
|
149
|
+
# capture_browser(writable, :format => "bmp", :only_drawing_area => true) {|image| ... }
|
150
|
+
#
|
151
|
+
# capture IE window and write to +writable+.
|
152
|
+
#
|
153
|
+
# * +writable+ is String, Pathname or object that implemented #write method (Such as IO stream).
|
154
|
+
# * +format+ is image format, "GIF" or "JPG" for example.
|
155
|
+
# * You can specify optional block argument to filter Magick::ImageList.
|
156
|
+
# If RMagick is not installed, block argument will ignore.
|
157
|
+
#
|
158
|
+
# ex):
|
159
|
+
#
|
160
|
+
# Win32::CaptureIE.start do |b|
|
161
|
+
# b.capture_browser("browser.bmp")
|
162
|
+
# b.capture_browser("browser.png", :only_drawing_area => true)
|
163
|
+
# open("browser.jpg", "wb") do |w|
|
164
|
+
# b.capture_browser(w, :format => "jpg")
|
165
|
+
# end
|
166
|
+
# end
|
167
|
+
#
|
168
|
+
# RMagick example:
|
94
169
|
#
|
95
|
-
#
|
96
|
-
|
97
|
-
|
170
|
+
# url = "http://win32-captureie.rubyforge.org/html/files/README_txt.html"
|
171
|
+
# Win32::CaptureIE.start(url) do |b|
|
172
|
+
# b.capture_page("readme.jpg") do |image|
|
173
|
+
# area = b.abs_element_area("description")
|
174
|
+
# gc = Magick::Draw.new
|
175
|
+
# gc.stroke = "red"
|
176
|
+
# gc.fill = "red"
|
177
|
+
# gc.stroke_width = 4
|
178
|
+
# gc.stroke_opacity(0.6)
|
179
|
+
# gc.fill_opacity(0.3)
|
180
|
+
# gc.rectangle(*area.rect)
|
181
|
+
# gc.draw(image)
|
182
|
+
# image
|
183
|
+
# end
|
184
|
+
# end
|
185
|
+
#
|
186
|
+
def capture_browser(writable, opts=nil, &rmagick_filter)
|
187
|
+
opts = parse_opts_for_capture_xxx(opts)
|
188
|
+
captor.capture_browser(opts).save(writable, opts[:format], &rmagick_filter)
|
98
189
|
end
|
99
190
|
|
100
|
-
#
|
101
|
-
|
102
|
-
|
191
|
+
# call-seq:
|
192
|
+
# capture_browser_image(:format => "bmp")
|
193
|
+
# capture_browser_image(:format => "bmp", :only_drawing_area => true)
|
194
|
+
#
|
195
|
+
# capture IE window and return Magick::ImageList or BitMap blob as String.
|
196
|
+
#
|
197
|
+
# * +format+ is image format, "GIF" or "JPG" for example.
|
198
|
+
#
|
199
|
+
# ex):
|
200
|
+
#
|
201
|
+
# Win32::CaptureIE.start do |b|
|
202
|
+
# b.capture_browser_image.write("foo.bmp")
|
203
|
+
# b.capture_browser_image(:format => "png").write("foo.png")
|
204
|
+
# end
|
205
|
+
#
|
206
|
+
def capture_browser_image(opts=nil)
|
207
|
+
opts = parse_opts_for_capture_xxx_image(opts)
|
208
|
+
captor.capture_browser(opts).to_image(opts[:format])
|
209
|
+
end
|
210
|
+
|
211
|
+
# call-seq:
|
212
|
+
# capture_page(writable, :format => "bmp")
|
213
|
+
# capture_page(writable, :format => "bmp") {|image| ... }
|
214
|
+
#
|
215
|
+
# capture whole web page and write to +writable+.
|
216
|
+
#
|
217
|
+
# see #capture_browser for more detail.
|
218
|
+
def capture_page(writable, opts=nil, &rmagick_filter)
|
219
|
+
opts = parse_opts_for_capture_xxx(opts)
|
220
|
+
captor.capture_page.save(writable, opts[:format], &rmagick_filter)
|
221
|
+
end
|
222
|
+
|
223
|
+
# capture whole web page and return Magick::ImageList or BitMap blob as String.
|
224
|
+
#
|
225
|
+
# see #capture_browser_image for more detail.
|
226
|
+
def capture_page_image(opts=nil)
|
227
|
+
opts = parse_opts_for_capture_xxx_image(opts)
|
228
|
+
captor.capture_page.to_image(opts[:format])
|
229
|
+
end
|
230
|
+
|
231
|
+
# call-seq:
|
232
|
+
# capture_elements(writable, ["id", "id2"], :format => "bmp")
|
233
|
+
# capture_elements(writable, ["id", "id2"], :format => "bmp") {|image| ... }
|
234
|
+
#
|
235
|
+
# Captures specified elements (outer bounding box of all elements)
|
236
|
+
# and write to +writable+.
|
237
|
+
#
|
238
|
+
# * +id_or_elements+ is ID of DOM element or WIN32OLE object.
|
239
|
+
#
|
240
|
+
# see #capture_browser for more detail.
|
241
|
+
def capture_elements(writable, id_or_elements, opts=nil, &rmagick_filter)
|
242
|
+
opts = parse_opts_for_capture_xxx(opts)
|
243
|
+
captor.capture_elements(*id_or_elements).save(writable, opts[:format], &rmagick_filter)
|
244
|
+
end
|
245
|
+
|
246
|
+
# capture specified elements and return Magick::ImageList or BitMap blob as String.
|
247
|
+
#
|
248
|
+
# see #capture_browser_image for more detail.
|
249
|
+
def capture_elements_image(id_or_elements, opts=nil)
|
250
|
+
opts = parse_opts_for_capture_xxx_image(opts)
|
251
|
+
captor.capture_elements(*id_or_elements).to_image(opts[:format])
|
252
|
+
end
|
253
|
+
|
254
|
+
|
255
|
+
def parse_opts_for_capture_xxx(opts)
|
256
|
+
r = parse_opts(opts, String => :format)
|
257
|
+
r[:format] = guess_format(r[:format])
|
258
|
+
r
|
259
|
+
end
|
260
|
+
private :parse_opts_for_capture_xxx
|
261
|
+
|
262
|
+
def parse_opts_for_capture_xxx_image(opts)
|
263
|
+
r = parse_opts(opts, String => :filename)
|
264
|
+
r[:format] = guess_format(r.delete(:filename))
|
265
|
+
r
|
266
|
+
end
|
267
|
+
private :parse_opts_for_capture_xxx_image
|
268
|
+
|
269
|
+
def parse_opts(opts, fallback)
|
270
|
+
opts ||= {}
|
271
|
+
return opts if Hash === opts
|
272
|
+
if key = fallback[opts.class]
|
273
|
+
return { key => opts }
|
274
|
+
end
|
275
|
+
raise ArgumentError, "Invalid options `#{opts.inspect}:#{opts.class}' (expected Hash)."
|
276
|
+
end
|
277
|
+
private :parse_opts
|
278
|
+
|
279
|
+
def guess_format(filename_or_format)
|
280
|
+
return nil if filename_or_format.nil? or filename_or_format == ""
|
281
|
+
ext = File.extname(filename_or_format)
|
282
|
+
if ext == ""
|
283
|
+
filename_or_format
|
284
|
+
else
|
285
|
+
ext.sub(/\A\./, "") # arrow :format => File.basename("foo.png")
|
286
|
+
end
|
103
287
|
end
|
288
|
+
private :guess_format
|
104
289
|
|
105
290
|
def captor
|
106
291
|
Win32::CaptureIE::ScreenCaptor.new(self)
|
@@ -58,6 +58,12 @@ module Win32::CaptureIE::CLI
|
|
58
58
|
parser.on("-o", "--output=FILE", "save capture to FILE") {|v|
|
59
59
|
opt.output = v
|
60
60
|
}
|
61
|
+
parser.on("-T", "--output-type=TYPE",
|
62
|
+
"save capture as image TYPE",
|
63
|
+
"Default: PNG (RMagick available)",
|
64
|
+
" or BMP (not available)") {|v|
|
65
|
+
opt.output_type = v
|
66
|
+
}
|
61
67
|
parser.on("-D", "--output-digest=ALGORITHM",
|
62
68
|
"use output filename as hex-encoded version",
|
63
69
|
"of a given URL",
|
@@ -9,13 +9,8 @@ module Win32::CaptureIE::Commands
|
|
9
9
|
module PrtIE #:nodoc:
|
10
10
|
|
11
11
|
class Option < OptionBase #:nodoc:
|
12
|
-
global_option :outdir, :wait, :output_digest
|
12
|
+
global_option :outdir, :wait, :output_type, :output_digest
|
13
13
|
local_option :output, :url
|
14
|
-
attr_reader :ext
|
15
|
-
|
16
|
-
def initialize
|
17
|
-
@ext = "bmp"
|
18
|
-
end
|
19
14
|
|
20
15
|
def check_options
|
21
16
|
raise_arg_error(url, "missing url argument")
|
@@ -39,10 +34,11 @@ module Win32::CaptureIE::Commands
|
|
39
34
|
|
40
35
|
def fixup!
|
41
36
|
self.wait = 0 if wait.nil? or wait < 0
|
37
|
+
self.output_type ||= Win32::CaptureIE.rmagick_available? ? "png" : "bmp"
|
42
38
|
end
|
43
39
|
|
44
40
|
def outfile
|
45
|
-
base = output || "#{digest_url}.#{
|
41
|
+
base = output || "#{digest_url}.#{output_type}"
|
46
42
|
r = File.expand_path(base, outdir)
|
47
43
|
dir = File.dirname(r)
|
48
44
|
::FileUtils.mkdir_p(dir) unless File.exist?(dir)
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "win32/capture_ie/base"
|
2
|
+
|
3
|
+
module Win32::CaptureIE
|
4
|
+
module Feature #:nodoc:
|
5
|
+
|
6
|
+
# see Win32::CaptureIE.disable_rmagick
|
7
|
+
class DisabledError < StandardError; end
|
8
|
+
|
9
|
+
DISABLED_FEATURE = []
|
10
|
+
|
11
|
+
module_function
|
12
|
+
|
13
|
+
def disable_feature(feature)
|
14
|
+
DISABLED_FEATURE << feature if feature_enable?(feature)
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def enable_feature(feature)
|
19
|
+
DISABLED_FEATURE.delete(feature)
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def feature_enable?(feature)
|
24
|
+
not DISABLED_FEATURE.include?(feature)
|
25
|
+
end
|
26
|
+
|
27
|
+
def feature_available?(feature)
|
28
|
+
begin
|
29
|
+
load_depended_library(feature, "test")
|
30
|
+
true
|
31
|
+
rescue LoadError, DisabledError => ignored
|
32
|
+
false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def raise_if_disabled(feature, function)
|
37
|
+
if DISABLED_FEATURE.include?(feature)
|
38
|
+
raise DisabledError, "`#{feature}' is disabled. " +
|
39
|
+
"Please enable `#{feature}' to #{function}."
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def load_feature(feature, function)
|
44
|
+
raise_if_disabled(feature, function)
|
45
|
+
require feature
|
46
|
+
end
|
47
|
+
|
48
|
+
def load_depended_library(feature, function)
|
49
|
+
begin
|
50
|
+
load_feature feature, function
|
51
|
+
rescue LoadError
|
52
|
+
begin
|
53
|
+
load_feature "rubygems", function
|
54
|
+
load_feature feature, function
|
55
|
+
rescue LoadError
|
56
|
+
raise LoadError, "no such file to load -- `#{feature}'. " +
|
57
|
+
"Please install `#{feature}' to #{function}."
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "win32/capture_ie/base"
|
2
2
|
require "win32/capture_ie/ffi"
|
3
3
|
require "win32/capture_ie/bitmap"
|
4
|
+
require "win32/capture_ie/area"
|
4
5
|
|
5
6
|
module Win32::CaptureIE
|
6
7
|
|
@@ -19,80 +20,92 @@ module Win32::CaptureIE
|
|
19
20
|
end
|
20
21
|
|
21
22
|
def capture_browser(opts=nil)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
capture_hwnd(h)
|
27
|
-
end
|
23
|
+
opts ||= {}
|
24
|
+
hwnd = opts[:only_drawing_area] ? browser.embedding_ie_hwnd : browser.hwnd
|
25
|
+
browser.bring_window_to_top
|
26
|
+
capture_hwnd(hwnd)
|
28
27
|
end
|
29
28
|
|
30
29
|
def capture_page
|
31
|
-
browser.
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
browser.bring_window_to_top
|
31
|
+
capture_area(browser.embedding_ie_hwnd, browser.body_area)
|
32
|
+
end
|
33
|
+
|
34
|
+
def capture_elements(*id_or_elements)
|
35
|
+
elems = id_or_elements.map{|e| [e, browser.to_element(e)] }
|
36
|
+
return capture_page if elems.find{|id, e| e.tagName.downcase == "body" }
|
37
|
+
|
38
|
+
area = elems.map {|id, e|
|
39
|
+
r = browser.abs_element_area(e)
|
40
|
+
if r.w.zero? or r.h.zero?
|
41
|
+
raise ArgumentError, "Invalid element: `#{id}' has no content. #{r}."
|
42
|
+
end
|
43
|
+
r
|
44
|
+
}.inject{|a,b| a + b }
|
45
|
+
|
46
|
+
browser.bring_window_to_top
|
47
|
+
capture_area(browser.embedding_ie_hwnd, area)
|
35
48
|
end
|
36
49
|
|
37
|
-
def capture_area(hwnd,
|
38
|
-
|
39
|
-
|
50
|
+
def capture_area(hwnd, area)
|
51
|
+
area.x = 0 if area.x < 0
|
52
|
+
area.y = 0 if area.y < 0
|
40
53
|
|
41
|
-
w = body.scrollWidth
|
42
|
-
h = body.scrollHeight -
|
54
|
+
area.w = body.scrollWidth - area.x if area.x + area.w > body.scrollWidth
|
55
|
+
area.h = body.scrollHeight - area.y if area.y + area.h > body.scrollHeight
|
43
56
|
|
44
57
|
# Scrolls the page so that top of the object is visible at the top of the window.
|
45
|
-
body.
|
46
|
-
body.
|
58
|
+
body.scrollLeft = area.x - 2
|
59
|
+
body.scrollTop = area.y - 2
|
47
60
|
|
48
61
|
# The position on the screen is different due to page scrolling and Body border
|
49
|
-
sx =
|
50
|
-
sy =
|
62
|
+
sx = area.x - body.scrollLeft + body.clientLeft
|
63
|
+
sy = area.y - body.scrollTop + body.clientTop
|
51
64
|
|
52
|
-
if sx + w < body.clientWidth && sy + h < body.clientHeight
|
65
|
+
if sx + area.w < body.clientWidth && sy + area.h < body.clientHeight
|
53
66
|
# If the whole object is visible
|
54
|
-
capture_hwnd_area(hwnd, sx, sy, w, h)
|
67
|
+
capture_hwnd_area(hwnd, Area.new(sx, sy, area.w, area.h))
|
55
68
|
else
|
56
69
|
# If only part of it is visible
|
57
|
-
capture_and_scroll(hwnd,
|
70
|
+
capture_and_scroll(hwnd, area)
|
58
71
|
end
|
59
72
|
end
|
60
73
|
|
61
|
-
def capture_and_scroll(hwnd,
|
74
|
+
def capture_and_scroll(hwnd, area)
|
62
75
|
# Captured area
|
63
76
|
result = BitMap.new(0, 0)
|
64
77
|
|
65
78
|
# We will do the screen capturing in more steps by areas of maximum dimensions maxw x maxh
|
66
|
-
maxw = body.clientWidth
|
67
|
-
maxh = body.clientHeight
|
79
|
+
maxw = body.clientWidth
|
80
|
+
maxh = body.clientHeight
|
68
81
|
|
69
82
|
cw = 0
|
70
83
|
ch = 0
|
71
84
|
cnt_x = 0
|
72
|
-
while cw < w
|
85
|
+
while cw < area.w
|
73
86
|
# Scroll to the top and right
|
74
|
-
body.scrollTop
|
75
|
-
body.scrollLeft =
|
87
|
+
body.scrollTop = area.x - 2
|
88
|
+
body.scrollLeft = area.x - 2 + cnt_x * (maxw * 0.9).to_i
|
76
89
|
|
77
|
-
ch = 0
|
90
|
+
ch = 0
|
78
91
|
cnt_y = 0
|
79
92
|
strip = BitMap.new(0, 0)
|
80
|
-
while ch < h
|
81
|
-
body.scrollTop =
|
93
|
+
while ch < area.h
|
94
|
+
body.scrollTop = area.x - 2 + cnt_y * (maxh * 0.9).to_i
|
82
95
|
|
83
96
|
# Recalculate the position on the screen
|
84
|
-
sx =
|
85
|
-
sy =
|
97
|
+
sx = area.x - body.scrollLeft + body.clientLeft + cw
|
98
|
+
sy = area.y - body.scrollTop + body.clientTop + ch
|
86
99
|
|
87
100
|
# Calculate the dimensions of the part to be captured
|
88
|
-
pw = (
|
89
|
-
pw = cw + pw > w ? w - cw : pw
|
101
|
+
pw = (area.x + cw - body.scrollLeft + maxw) > maxw ? maxw - (area.x + cw) + body.scrollLeft : maxw
|
102
|
+
pw = cw + pw > area.w ? area.w - cw : pw
|
90
103
|
|
91
|
-
ph = (
|
92
|
-
ph = ch + ph > h ? h - ch : ph
|
104
|
+
ph = (area.y + ch - body.scrollTop + maxh) > maxh ? maxh - (area.y + ch) + body.scrollTop : maxh
|
105
|
+
ph = ch + ph > area.h ? area.h - ch : ph
|
93
106
|
|
94
107
|
# Capture the part and append it to the strip
|
95
|
-
strip << capture_hwnd_area(hwnd, sx, sy, pw, ph)
|
108
|
+
strip << capture_hwnd_area(hwnd, Area.new(sx, sy, pw, ph))
|
96
109
|
ch += ph
|
97
110
|
cnt_y += 1
|
98
111
|
end
|
@@ -107,19 +120,19 @@ module Win32::CaptureIE
|
|
107
120
|
|
108
121
|
def capture_hwnd(hwnd)
|
109
122
|
left, top, right, bottom = get_window_rect(hwnd)
|
110
|
-
capture_hwnd_area(hwnd, 0, 0, right - left, bottom - top)
|
123
|
+
capture_hwnd_area(hwnd, Area.new(0, 0, right - left, bottom - top))
|
111
124
|
end
|
112
125
|
|
113
|
-
def capture_hwnd_area(hwnd,
|
126
|
+
def capture_hwnd_area(hwnd, area)
|
114
127
|
with_window_dc(hwnd) do |hdc|
|
115
128
|
with_delete_dc(CreateCompatibleDC(hdc)) do |memdc|
|
116
|
-
with_delete_object(CreateCompatibleBitmap(hdc, w, h)) do |hbmp|
|
129
|
+
with_delete_object(CreateCompatibleBitmap(hdc, area.w, area.h)) do |hbmp|
|
117
130
|
SelectObject(memdc, hbmp)
|
118
|
-
BitBlt(memdc, 0, 0, w, h, hdc, x, y, SRCCOPY)
|
131
|
+
BitBlt(memdc, 0, 0, area.w, area.h, hdc, area.x, area.y, SRCCOPY)
|
119
132
|
|
120
|
-
bmp = BitMap.new(w, h)
|
121
|
-
r = GetDIBits(memdc, hbmp, 0, h, bmp.data, bmp.info.pack, DIB_RGB_COLORS)
|
122
|
-
raise Win32APIError, "GetDIBits failed: #{r}" if r.nil? or r.zero?
|
133
|
+
bmp = BitMap.new(area.w, area.h)
|
134
|
+
r = GetDIBits(memdc, hbmp, 0, area.h, bmp.data, bmp.info.pack, DIB_RGB_COLORS)
|
135
|
+
raise Win32APIError, "GetDIBits failed: #{r}: #{[hwnd, area].inspect}" if r.nil? or r.zero?
|
123
136
|
|
124
137
|
bmp
|
125
138
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Win32::CaptureIE
|
2
|
+
module Util #:nodoc:
|
3
|
+
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def maybe_enable_binmode(obj)
|
7
|
+
obj.binmode if obj.respond_to?(:binmode)
|
8
|
+
end
|
9
|
+
|
10
|
+
def filename_type
|
11
|
+
r = []
|
12
|
+
r << ::String
|
13
|
+
r << ::Pathname if defined?(::Pathname)
|
14
|
+
r
|
15
|
+
end
|
16
|
+
|
17
|
+
def with_filename_or_writable(duck, opts)
|
18
|
+
if filename_type.any?{|t| t === duck }
|
19
|
+
maybe_enable_binmode(duck)
|
20
|
+
opts[:if_filename].call(duck)
|
21
|
+
elsif duck.respond_to?(:write)
|
22
|
+
opts[:if_writable].call(duck)
|
23
|
+
else
|
24
|
+
raise ArgumentError, "`#{duck.inspect}' (#{duck.class}) " +
|
25
|
+
"should be writable object or filename (String or Pathname)."
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def guess_format(writable, default="bmp")
|
30
|
+
r = with_filename_or_writable(writable, {
|
31
|
+
:if_writable => lambda { "" },
|
32
|
+
:if_filename => lambda { File.extname(writable).downcase.sub(/\A\./, "") },
|
33
|
+
})
|
34
|
+
(r == "") ? default : r
|
35
|
+
end
|
36
|
+
|
37
|
+
def with_output_stream(duck, &block)
|
38
|
+
with_filename_or_writable(duck, {
|
39
|
+
:if_writable => lambda { block.call(duck) },
|
40
|
+
:if_filename => lambda { open(duck, "wb", &block) },
|
41
|
+
})
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
data/spec/spec.opts
CHANGED
@@ -1 +0,0 @@
|
|
1
|
-
--colour
|
data/spec/spec_helper.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), "../lib")
|
2
|
+
require "win32/capture_ie"
|
3
|
+
|
4
|
+
require "rubygems"
|
5
|
+
require "spec"
|
6
|
+
|
7
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__))
|
8
|
+
require "dsl/behaviour_eval"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "../../spec_helper.rb")
|
2
|
+
require "win32/capture_ie/area"
|
3
|
+
|
4
|
+
describe Win32::CaptureIE::Area do
|
5
|
+
|
6
|
+
it "#bottom_right" do
|
7
|
+
area = Win32::CaptureIE::Area.new(200, 300, 10, 20)
|
8
|
+
area.bottom_right == [200, 200, 210, 320]
|
9
|
+
end
|
10
|
+
|
11
|
+
it "#+" do
|
12
|
+
area1 = Win32::CaptureIE::Area.new(0, 0, 100, 100)
|
13
|
+
area2 = Win32::CaptureIE::Area.new(200, 200, 10, 10)
|
14
|
+
area3 = area1 + area2
|
15
|
+
area3.top_left.should == [0, 0]
|
16
|
+
area3.bottom_right.should == [210, 210]
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
data/tasks/deployment.rake
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
desc 'Release the website and new gem version'
|
2
|
-
task :deploy => [:check_version, :
|
2
|
+
task :deploy => [:check_version, :publish_docs, :release] do
|
3
3
|
puts "Remember to create SVN tag:"
|
4
4
|
puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
|
5
5
|
"svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
|
data/tasks/deployment2.rake
CHANGED
@@ -67,8 +67,9 @@ if ENV["SCP"] and ENV["SCP"] != "scp"
|
|
67
67
|
end
|
68
68
|
|
69
69
|
|
70
|
+
NEWS_FILE = "news.txt"
|
70
71
|
task :create_news do
|
71
|
-
subject, title, body, urls =
|
72
|
+
subject, title, body, urls = HOE.announcement
|
72
73
|
open(NEWS_FILE, "w") do |w|
|
73
74
|
w.puts subject
|
74
75
|
w.puts "#{title}\n\n#{body}\n\n"
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: win32-captureie
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-
|
6
|
+
version: 0.2.0
|
7
|
+
date: 2007-12-09 00:00:00 +09:00
|
8
8
|
summary: Win32::CaptureIE - Capture web pages using Internet Explorer
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -38,7 +38,11 @@ files:
|
|
38
38
|
- bin/prtie
|
39
39
|
- config/hoe.rb
|
40
40
|
- config/requirements.rb
|
41
|
+
- examples/capture-ruby-lang.rb
|
42
|
+
- examples/each_ie.rb
|
43
|
+
- examples/hilight-id.rb
|
41
44
|
- lib/win32/capture_ie.rb
|
45
|
+
- lib/win32/capture_ie/area.rb
|
42
46
|
- lib/win32/capture_ie/base.rb
|
43
47
|
- lib/win32/capture_ie/bitmap.rb
|
44
48
|
- lib/win32/capture_ie/browser.rb
|
@@ -46,12 +50,14 @@ files:
|
|
46
50
|
- lib/win32/capture_ie/cli/prt_ie.rb
|
47
51
|
- lib/win32/capture_ie/commands/base.rb
|
48
52
|
- lib/win32/capture_ie/commands/prt_ie.rb
|
53
|
+
- lib/win32/capture_ie/feature.rb
|
49
54
|
- lib/win32/capture_ie/ffi.rb
|
50
55
|
- lib/win32/capture_ie/ffi/base.rb
|
51
56
|
- lib/win32/capture_ie/ffi/gdi32.rb
|
52
57
|
- lib/win32/capture_ie/ffi/struct.rb
|
53
58
|
- lib/win32/capture_ie/ffi/user32.rb
|
54
59
|
- lib/win32/capture_ie/screen_captor.rb
|
60
|
+
- lib/win32/capture_ie/util.rb
|
55
61
|
- lib/win32/capture_ie/version.rb
|
56
62
|
- lib/win32/capture_ie/window.rb
|
57
63
|
- script/destroy
|
@@ -62,8 +68,10 @@ files:
|
|
62
68
|
- script/txt2html
|
63
69
|
- script/txt2html.cmd
|
64
70
|
- setup.rb
|
71
|
+
- spec/dsl/behaviour_eval.rb
|
65
72
|
- spec/spec.opts
|
66
73
|
- spec/spec_helper.rb
|
74
|
+
- spec/win32/capture_ie/area_spec.rb
|
67
75
|
- spec/win32/capture_ie_spec.rb
|
68
76
|
- tasks/deployment.rake
|
69
77
|
- tasks/deployment2.rake
|
@@ -73,7 +81,6 @@ files:
|
|
73
81
|
- tasks/helper/rake_sh_filter.rb
|
74
82
|
- tasks/helper/util.rb
|
75
83
|
- tasks/rspec.rake
|
76
|
-
- tasks/website.rake
|
77
84
|
test_files: []
|
78
85
|
|
79
86
|
rdoc_options:
|
data/tasks/website.rake
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
desc 'Generate website files'
|
2
|
-
task :website_generate => :ruby_env do
|
3
|
-
(Dir['website/**/*.txt'] - Dir['website/version*.txt']).each do |txt|
|
4
|
-
sh %{ #{RUBY_APP} script/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
|
5
|
-
end
|
6
|
-
end
|
7
|
-
|
8
|
-
desc 'Upload website files to rubyforge'
|
9
|
-
task :website_upload do
|
10
|
-
host = "#{rubyforge_username}@rubyforge.org"
|
11
|
-
remote_dir = "/var/www/gforge-projects/#{PATH}/"
|
12
|
-
local_dir = 'website'
|
13
|
-
sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}}
|
14
|
-
end
|
15
|
-
|
16
|
-
desc 'Generate and upload website files'
|
17
|
-
task :website => [:website_generate, :website_upload, :publish_docs]
|