/
windowstate.rb
153 lines (119 loc) · 2.94 KB
/
windowstate.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
require 'json'
require 'tmpdir'
require 'windows/window'
module Windows
module Window
API.new('SetWindowPlacement', 'LP', 'B', 'user32')
end
end
include Windows::Window
include Win32
class WindowPlacement
include Windows::Window
attr_reader :data_encoded, :handle
def self.get(handle)
wp = new(handle)
wp.get
wp
end
def self.json_create(o)
wp = new(o['data'][0])
wp.data = o['data'][1]
wp
end
def initialize(handle)
@handle = handle
end
def get
buffer = [44].pack("L") + '\0' * 40
GetWindowPlacement(handle, buffer)
@data_encoded = buffer
end
def set
SetWindowPlacement(handle, data_encoded)
end
def data
data_encoded.unpack("L11")
end
def data=(array)
@data_encoded = array.pack("L11")
end
def to_json(*a)
{
'json_class' => self.class.name,
'data' => [handle, data]
}.to_json(*a)
end
end
class WindowInfo
include Windows::Window
WS_CAPTION = 0x00C00000
WS_CHILD = 0x40000000
WS_CLIPSIBLINGS = 0x04000000
WS_DISABLED = 0x08000000
WS_DLGFRAME = 0x00400000
WS_POPUP = 0x80000000
WS_SIZEBOX = 0x00040000
WS_SYSMENU = 0x00080000
WS_VISIBLE = 0x10000000
attr_reader :data_encoded, :handle
def self.get(handle)
wp = new(handle)
wp.get
wp
end
def initialize(handle)
@handle = handle
end
def get
buffer = [60].pack("L") + '\0' * 56
GetWindowInfo(handle, buffer)
@data_encoded = buffer
end
def data
data_encoded.unpack("L14S2")
end
def style
data[9]
end
def ignorable?
style & (WS_DISABLED | WS_CHILD) > 0
end
def application_window?
mask = (WS_SYSMENU | WS_VISIBLE)
(style & mask == mask) && !ignorable?
end
def data=(array)
@data_encoded = array.pack("L14S2")
end
def to_json(*a)
{
'json_class' => self.class.name,
'data' => [handle, data]
}.to_json(*a)
end
end
window_placements = []
EnumWindowsProc = API::Callback.new('LP', 'I') do |handle, param|
title_buffer = "\0" * 200
rect_buffer = "\0" * 32
GetWindowText(handle, title_buffer, 200)
GetWindowRect(handle, rect_buffer)
wp = WindowPlacement.get(handle)
wi = WindowInfo.get(handle)
left, top, right, bottom = rect_buffer.unpack("L4")
if wi.application_window?
puts "#{handle} : #{title_buffer.strip} : #{left},#{top} #{right},#{bottom} : #{wi.data} : 0x#{wi.style.to_s(16)}"
window_placements << wp
true
end
true
end
EnumWindows(EnumWindowsProc, nil)
#File.open(File.join(Dir.tmpdir, "windowstate.json"), "w") do |dump_file|
# dump_file.puts JSON.generate(window_placements, object_nl: "\n")
#end
window_placements_read = JSON.parse(File.read(File.join(Dir.tmpdir, "windowstate.json")))
#console_window_placement = window_placements_read.find { |window| window.handle == 201280 }
#console_window_placement.set
window_placements_read.each { |wp| wp.set }