windows_gui 2.0.0

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.
@@ -0,0 +1,252 @@
1
+ require_relative 'common'
2
+
3
+ module WindowsGUI
4
+ ffi_lib 'kernel32'
5
+ ffi_convention :stdcall
6
+
7
+ attach_function :SetLastError, [
8
+ :ulong
9
+ ], :void
10
+
11
+ attach_function :GetLastError, [
12
+
13
+ ], :ulong
14
+
15
+ def Detonate(on, name, *args)
16
+ raise "#{name} failed" if
17
+ (failed = [*on].include?(result = send(name, *args)))
18
+
19
+ result
20
+ ensure
21
+ yield failed if block_given?
22
+ end
23
+
24
+ def DetonateLastError(on, name, *args)
25
+ raise "#{name} failed (last error: #{GetLastError()})" if
26
+ (failed = [*on].include?(result = send(name, *args)))
27
+
28
+ result
29
+ ensure
30
+ yield failed if block_given?
31
+ end
32
+
33
+ module_function :Detonate, :DetonateLastError
34
+
35
+ class OSVERSIONINFOEX < FFI::Struct
36
+ extend Util::ScopedStruct
37
+
38
+ layout \
39
+ :dwOSVersionInfoSize, :ulong,
40
+ :dwMajorVersion, :ulong,
41
+ :dwMinorVersion, :ulong,
42
+ :dwBuildNumber, :ulong,
43
+ :dwPlatformId, :ulong,
44
+ :szCSDVersion, [:ushort, 128],
45
+ :wServicePackMajor, :ushort,
46
+ :wServicePackMinor, :ushort,
47
+ :wSuiteMask, :ushort,
48
+ :wProductType, :uchar,
49
+ :wReserved, :uchar
50
+ end
51
+
52
+ attach_function :GetVersionEx, :GetVersionExW, [
53
+ OSVERSIONINFOEX.by_ref
54
+ ], :int
55
+
56
+ OSVERSION = OSVERSIONINFOEX.new.tap { |ovi|
57
+ at_exit { OSVERSION.pointer.free }
58
+
59
+ ovi[:dwOSVersionInfoSize] = ovi.size
60
+
61
+ DetonateLastError(0, :GetVersionEx,
62
+ ovi
63
+ )
64
+ }
65
+
66
+ NTDDI_WIN2K = 0x0500_0000
67
+
68
+ NTDDI_WIN2KSP1 = 0x0500_0100
69
+ NTDDI_WIN2KSP2 = 0x0500_0200
70
+ NTDDI_WIN2KSP3 = 0x0500_0300
71
+ NTDDI_WIN2KSP4 = 0x0500_0400
72
+
73
+ NTDDI_WINXP = 0x0501_0000
74
+
75
+ NTDDI_WINXPSP1 = 0x0501_0100
76
+ NTDDI_WINXPSP2 = 0x0501_0200
77
+ NTDDI_WINXPSP3 = 0x0501_0300
78
+ NTDDI_WINXPSP4 = 0x0501_0400
79
+
80
+ NTDDI_WS03 = 0x0502_0000
81
+
82
+ NTDDI_WS03SP1 = 0x0502_0100
83
+ NTDDI_WS03SP2 = 0x0502_0200
84
+ NTDDI_WS03SP3 = 0x0502_0300
85
+ NTDDI_WS03SP4 = 0x0502_0400
86
+
87
+ NTDDI_VISTA = 0x0600_0000
88
+
89
+ NTDDI_VISTASP1 = 0x0600_0100
90
+ NTDDI_VISTASP2 = 0x0600_0200
91
+ NTDDI_VISTASP3 = 0x0600_0300
92
+ NTDDI_VISTASP4 = 0x0600_0400
93
+
94
+ NTDDI_WS08 = NTDDI_VISTASP1
95
+
96
+ NTDDI_WS08SP2 = NTDDI_VISTASP2
97
+ NTDDI_WS08SP3 = NTDDI_VISTASP3
98
+ NTDDI_WS08SP4 = NTDDI_VISTASP4
99
+
100
+ NTDDI_WIN7 = 0x0601_0000
101
+
102
+ NTDDI_VERSION = MAKELONG(
103
+ MAKEWORD(OSVERSION[:wServicePackMinor], OSVERSION[:wServicePackMajor]),
104
+ MAKEWORD(OSVERSION[:dwMinorVersion], OSVERSION[:dwMajorVersion])
105
+ )
106
+
107
+ WIN2K = 0x0500
108
+ WINXP = 0x0501
109
+ WINVISTA = 0x0600
110
+ WIN7 = 0x0601
111
+
112
+ WINVER = HIWORD(NTDDI_VERSION)
113
+
114
+ def TARGETVER(version, message)
115
+ version = MAKELONG(0x0000, version) if version < 0xffff
116
+
117
+ exit(-1) if NTDDI_VERSION < version &&
118
+ MessageBox(nil,
119
+ message,
120
+ APPNAME,
121
+ MB_YESNO | MB_ICONERROR | MB_DEFBUTTON2
122
+ ) == IDNO
123
+ end
124
+
125
+ module_function :TARGETVER
126
+
127
+ attach_function :GetModuleHandle, :GetModuleHandleW, [
128
+ :buffer_in
129
+ ], :pointer
130
+
131
+ attach_function :LoadLibrary, :LoadLibraryW, [
132
+ :buffer_in
133
+ ], :pointer
134
+
135
+ attach_function :FreeLibrary, [
136
+ :pointer
137
+ ], :int
138
+
139
+ if WINVER >= WINXP
140
+ class ACTCTX < FFI::Struct
141
+ extend Util::ScopedStruct
142
+
143
+ layout \
144
+ :cbSize, :ulong,
145
+ :dwFlags, :ulong,
146
+ :lpSource, :pointer,
147
+ :wProcessorArchitecture, :ushort,
148
+ :wLangId, :ushort,
149
+ :lpAssemblyDirectory, :pointer,
150
+ :lpResourceName, :pointer,
151
+ :lpApplicationName, :pointer,
152
+ :hModule, :pointer
153
+ end
154
+
155
+ attach_function :CreateActCtx, :CreateActCtxW, [
156
+ ACTCTX.by_ref
157
+ ], :pointer
158
+
159
+ attach_function :ReleaseActCtx, [
160
+ :pointer
161
+ ], :void
162
+
163
+ attach_function :ActivateActCtx, [
164
+ :pointer,
165
+ :pointer
166
+ ], :int
167
+
168
+ attach_function :DeactivateActCtx, [
169
+ :ulong,
170
+ :ulong
171
+ ], :int
172
+
173
+ COMMON_CONTROLS_ACTCTX = {
174
+ handle: INVALID_HANDLE_VALUE,
175
+ cookie: FFI::MemoryPointer.new(:ulong),
176
+ activated: false
177
+ }
178
+
179
+ at_exit {
180
+ DeactivateActCtx(0, COMMON_CONTROLS_ACTCTX[:cookie].get_ulong(0)) if
181
+ COMMON_CONTROLS_ACTCTX[:activated]
182
+
183
+ ReleaseActCtx(COMMON_CONTROLS_ACTCTX[:handle]) unless
184
+ COMMON_CONTROLS_ACTCTX[:handle] == INVALID_HANDLE_VALUE
185
+
186
+ COMMON_CONTROLS_ACTCTX[:cookie].free
187
+ }
188
+ end
189
+
190
+ def EnableVisualStyles
191
+ return unless WINVER >= WINXP
192
+
193
+ raise 'Visual styles already enabled' if
194
+ COMMON_CONTROLS_ACTCTX[:activated]
195
+
196
+ manifest = "#{ENV['TEMP']}/windows_gui.manifest"
197
+
198
+ File.open(manifest, 'w:utf-8') { |file|
199
+ file << <<-XML
200
+ <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
201
+ <assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
202
+ <dependency>
203
+ <dependentAssembly>
204
+ <assemblyIdentity
205
+ type='Win32'
206
+ name='Microsoft.Windows.Common-Controls'
207
+ version='6.0.0.0'
208
+ processorArchitecture='*'
209
+ publicKeyToken='6595b64144ccf1df'
210
+ language='*'
211
+ />
212
+ </dependentAssembly>
213
+ </dependency>
214
+ </assembly>
215
+ XML
216
+ }
217
+
218
+ ACTCTX.new { |ac|
219
+ ac[:cbSize] = ac.size
220
+
221
+ PWSTR(L(manifest)) { |source|
222
+ ac[:lpSource] = source
223
+
224
+ COMMON_CONTROLS_ACTCTX[:handle] =
225
+ DetonateLastError(INVALID_HANDLE_VALUE, :CreateActCtx,
226
+ ac
227
+ )
228
+ }
229
+ }
230
+
231
+ DetonateLastError(0, :ActivateActCtx,
232
+ COMMON_CONTROLS_ACTCTX[:handle], COMMON_CONTROLS_ACTCTX[:cookie]
233
+ ) { |failed|
234
+ next unless failed
235
+
236
+ ReleaseActCtx(COMMON_CONTROLS_ACTCTX[:handle])
237
+ COMMON_CONTROLS_ACTCTX[:handle] = INVALID_HANDLE_VALUE
238
+ }
239
+
240
+ COMMON_CONTROLS_ACTCTX[:activated] = true
241
+ end
242
+
243
+ module_function :EnableVisualStyles
244
+
245
+ EnableVisualStyles() if WINDOWS_GUI_VISUAL_STYLES
246
+
247
+ attach_function :MulDiv, [
248
+ :int,
249
+ :int,
250
+ :int
251
+ ], :int
252
+ end
@@ -0,0 +1,10 @@
1
+ require_relative 'common'
2
+
3
+ module WindowsGUI
4
+ ffi_lib FFI::Library::LIBC
5
+ ffi_convention :cdecl
6
+
7
+ attach_function :wcslen, [
8
+ :buffer_in
9
+ ], :uint
10
+ end