fzeet 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/examples/Dialog/FileDialog.rbw +34 -0
  2. data/examples/Raw/UIRibbon/Command.dll +0 -0
  3. data/examples/Raw/UIRibbon/Command.rb +22 -0
  4. data/examples/Raw/UIRibbon/Command.rbw +51 -0
  5. data/examples/Raw/UIRibbon/Command.xml +65 -0
  6. data/examples/Raw/UIRibbon/Minimal.dll +0 -0
  7. data/examples/Raw/UIRibbon/Minimal.rb +16 -0
  8. data/examples/Raw/UIRibbon/Minimal.rbw +39 -0
  9. data/examples/Raw/UIRibbon/Minimal.xml +55 -0
  10. data/examples/UIRibbon/Command.dll +0 -0
  11. data/examples/UIRibbon/Command.rb +22 -0
  12. data/examples/UIRibbon/Command.rbw +20 -0
  13. data/examples/UIRibbon/Command.xml +65 -0
  14. data/examples/UIRibbon/Minimal.dll +0 -0
  15. data/examples/UIRibbon/Minimal.rb +16 -0
  16. data/examples/UIRibbon/Minimal.rbw +8 -0
  17. data/examples/UIRibbon/Minimal.xml +55 -0
  18. data/examples/UIRibbon/Viewer.rbw +9 -0
  19. data/examples/res/go-next-small.bmp +0 -0
  20. data/examples/res/go-next.bmp +0 -0
  21. data/examples/res/go-previous-small.bmp +0 -0
  22. data/examples/res/go-previous.bmp +0 -0
  23. data/lib/fzeet/Control.rb +1 -89
  24. data/lib/fzeet/ControlButton.rb +28 -0
  25. data/lib/fzeet/ControlCommon.rb +64 -0
  26. data/lib/fzeet/Dialog.rb +1 -0
  27. data/lib/fzeet/DialogCommon.rb +5 -0
  28. data/lib/fzeet/DialogFileDialog.rb +116 -0
  29. data/lib/fzeet/UIRibbon.rb +99 -0
  30. data/lib/fzeet/Window.rb +2 -336
  31. data/lib/fzeet/WindowCommon.rb +256 -0
  32. data/lib/fzeet/WindowDialog.rb +73 -0
  33. data/lib/fzeet/WindowWindow.rb +13 -0
  34. data/lib/fzeet/common.rb +2 -0
  35. data/lib/fzeet/windows/com.rb +186 -0
  36. data/lib/fzeet/windows/comctl.rb +1 -59
  37. data/lib/fzeet/windows/comctlbutton.rb +30 -0
  38. data/lib/fzeet/windows/comctlcommon.rb +34 -0
  39. data/lib/fzeet/windows/comdlg.rb +1 -0
  40. data/lib/fzeet/windows/comdlgcommon.rb +9 -0
  41. data/lib/fzeet/windows/comdlgofn.rb +70 -0
  42. data/lib/fzeet/windows/common.rb +18 -0
  43. data/lib/fzeet/windows/kernel.rb +3 -0
  44. data/lib/fzeet/windows/libc.rb +1 -0
  45. data/lib/fzeet/windows/ole.rb +213 -0
  46. data/lib/fzeet/windows/shell.rb +43 -0
  47. data/lib/fzeet/windows/uiribbon.rb +111 -0
  48. data/lib/fzeet/windows/user.rb +7 -438
  49. data/lib/fzeet/windows/usercommon.rb +8 -0
  50. data/lib/fzeet/windows/userctl.rb +1 -68
  51. data/lib/fzeet/windows/userctlbutton.rb +56 -0
  52. data/lib/fzeet/windows/userctlcommon.rb +12 -0
  53. data/lib/fzeet/windows/userkbd.rb +20 -0
  54. data/lib/fzeet/windows/usermbox.rb +62 -0
  55. data/lib/fzeet/windows/usermenu.rb +50 -0
  56. data/lib/fzeet/windows/usermsg.rb +1 -6
  57. data/lib/fzeet/windows/userspi.rb +29 -0
  58. data/lib/fzeet/windows/userwnd.rb +276 -0
  59. data/lib/fzeet/windows.rb +24 -4
  60. data/lib/fzeet.rb +2 -0
  61. metadata +54 -6
  62. /data/examples/{Dialog.rbw → Dialog/Dialog.rbw} +0 -0
  63. /data/examples/{DialogApplication.rbw → Dialog/DialogApplication.rbw} +0 -0
@@ -0,0 +1,256 @@
1
+ require_relative 'WindowMethods'
2
+
3
+ module Fzeet
4
+ class BasicWindow < Handle
5
+ include WindowMethods
6
+
7
+ Prefix = {
8
+ xstyle: [:ws_ex_],
9
+ style: [:ws_, :ds_],
10
+ message: [:wm_],
11
+ notification: []
12
+ }
13
+
14
+ WindowProc = FFI::Function.new(:long, [:pointer, :uint, :uint, :long], convention: :stdcall) { |hwnd, uMsg, wParam, lParam|
15
+ begin
16
+ if uMsg == Windows::WM_NCCREATE
17
+ @@instances[hwnd.to_i] = ObjectSpace._id2ref(
18
+ Windows::CREATESTRUCT.new(FFI::Pointer.new(lParam))[:lpCreateParams].to_i
19
+ )
20
+
21
+ @@instances[hwnd.to_i].instance_variable_set(:@handle, hwnd)
22
+ end
23
+
24
+ result = @@instances[hwnd.to_i].windowProc(hwnd, uMsg, wParam, lParam) if @@instances[hwnd.to_i]
25
+ rescue
26
+ answer = Fzeet.message %Q{#{$!}\n\n#{$!.backtrace.join("\n")}}, buttons: [:abort, :retry, :ignore], icon: :error
27
+
28
+ Application.quit if answer.abort?
29
+ ensure
30
+ if uMsg == Windows::WM_NCDESTROY
31
+ @@instances[hwnd.to_i].dialog = false
32
+
33
+ @@instances.delete(hwnd.to_i)
34
+ end
35
+ end
36
+
37
+ result || Windows.DefWindowProc(hwnd, uMsg, wParam, lParam)
38
+ }
39
+
40
+ DialogProc = FFI::Function.new(:int, [:pointer, :uint, :uint, :long], convention: :stdcall) { |hwnd, uMsg, wParam, lParam|
41
+ begin
42
+ if uMsg == Windows::WM_INITDIALOG
43
+ @@instances[hwnd.to_i] = ObjectSpace._id2ref(lParam)
44
+
45
+ @@instances[hwnd.to_i].instance_variable_set(:@handle, hwnd)
46
+ end
47
+
48
+ result = @@instances[hwnd.to_i].windowProc(hwnd, uMsg, wParam, lParam) if @@instances[hwnd.to_i]
49
+ rescue
50
+ answer = Fzeet.message %Q{#{$!}\n\n#{$!.backtrace.join("\n")}}, buttons: [:abort, :retry, :ignore], icon: :error
51
+
52
+ Application.quit if answer.abort?
53
+ ensure
54
+ if uMsg == Windows::WM_NCDESTROY
55
+ @@instances[hwnd.to_i].dialog = false
56
+
57
+ @@instances.delete(hwnd.to_i)
58
+ end
59
+ end
60
+
61
+ (result.nil?) ? 0 : 1
62
+ }
63
+
64
+ WindowClass = Fzeet::WindowClass.new(nil, 'Fzeet.BasicWindow')
65
+
66
+ def self.[](name, opts = {})
67
+ Class.new(self) { |klass|
68
+ klass.const_set(:WindowClass, Fzeet::WindowClass.new(self::WindowClass, name, opts))
69
+ }
70
+ end
71
+
72
+ def self.crackMessage(hwnd, uMsg, wParam, lParam)
73
+ window = @@instances[hwnd.to_i]
74
+
75
+ args = {
76
+ hwnd: hwnd,
77
+ uMsg: uMsg,
78
+ wParam: wParam,
79
+ lParam: lParam,
80
+ result: (window.kind_of?(Dialog)) ? 1 : 0,
81
+ window: window,
82
+ sender: window
83
+ }
84
+
85
+ case uMsg
86
+ when Windows::WM_CREATE
87
+ args[:cs] = Windows::CREATESTRUCT.new(FFI::Pointer.new(lParam))
88
+ when Windows::WM_NCCREATE
89
+ args[:result] = 1
90
+ args[:cs] = Windows::CREATESTRUCT.new(FFI::Pointer.new(lParam))
91
+ when Windows::WM_COMMAND
92
+ args[:command], args[:notification], args[:hctl] = Windows.LOWORD(wParam), Windows.HIWORD(wParam), FFI::Pointer.new(lParam)
93
+ args[:sender] = @@instances[args[:hctl].to_i] unless args[:hctl].null?
94
+ when Windows::WM_NOTIFY
95
+ args[:nmh] = Windows::NMHDR.new(FFI::Pointer.new(lParam))
96
+ args[:command], args[:notification], args[:hctl] = args[:nmh][:idFrom], args[:nmh][:code], args[:nmh][:hwndFrom]
97
+ (args[:sender] = @@instances[args[:hctl].to_i]).class.crackNotification(args)
98
+ when \
99
+ Windows::WM_MOUSEMOVE,
100
+ Windows::WM_LBUTTONDOWN, Windows::WM_LBUTTONUP, Windows::WM_LBUTTONDBLCLK,
101
+ Windows::WM_RBUTTONDOWN, Windows::WM_RBUTTONUP, Windows::WM_RBUTTONDBLCLK,
102
+ Windows::WM_MBUTTONDOWN, Windows::WM_MBUTTONUP, Windows::WM_MBUTTONDBLCLK,
103
+ Windows::WM_CONTEXTMENU
104
+
105
+ args[:x], args[:y] = Windows.GET_X_LPARAM(lParam), Windows.GET_Y_LPARAM(lParam)
106
+
107
+ if uMsg == Windows::WM_CONTEXTMENU && args[:x] == -1
108
+ Windows.DetonateLastError(0, :GetCursorPos, pt = Point.new)
109
+
110
+ args[:keyboard], args[:x], args[:y] = true, pt[:x], pt[:y]
111
+ end
112
+ end
113
+
114
+ args
115
+ end
116
+
117
+ def initialize(opts = {})
118
+ _opts = {
119
+ xstyle: [],
120
+ caption: Application.name,
121
+ style: [],
122
+ x: Windows::CW_USEDEFAULT,
123
+ y: Windows::CW_USEDEFAULT,
124
+ width: Windows::CW_USEDEFAULT,
125
+ height: Windows::CW_USEDEFAULT,
126
+ parent: nil,
127
+ menu: nil
128
+ }
129
+ badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
130
+ _opts.merge!(opts)
131
+
132
+ yield self, _opts if block_given?
133
+
134
+ _opts[:xstyle] = Fzeet.flags(_opts[:xstyle], *self.class::Prefix[:xstyle])
135
+ _opts[:caption] = _opts[:caption].to_s
136
+ _opts[:style] = Fzeet.flags(_opts[:style], *self.class::Prefix[:style])
137
+
138
+ @messages ||= {}
139
+ @commands ||= {}
140
+ @notifies ||= {}
141
+
142
+ @processed = [0, 0]
143
+
144
+ @handle = Windows.CreateWindowEx(
145
+ _opts[:xstyle], self.class::WindowClass.name, _opts[:caption], _opts[:style],
146
+ _opts[:x], _opts[:y], _opts[:width], _opts[:height],
147
+ _opts[:parent] && _opts[:parent].handle, nil, Windows.GetModuleHandle(nil), FFI::Pointer.new(object_id)
148
+ )
149
+
150
+ if @handle.null?
151
+ raise "CreateWindowEx failed (last error #{Windows.GetLastError()})." unless [
152
+ [Windows::WM_NCCREATE, 0], [Windows::WM_CREATE, -1],
153
+ [Windows::WM_DESTROY, 0], [Windows::WM_NCDESTROY, 0]
154
+ ].include?(@processed)
155
+ else
156
+ @parent = _opts[:parent]
157
+ self.menu = _opts[:menu] if _opts[:menu]
158
+
159
+ on(:destroy) {
160
+ menu.rdetach if self.menu
161
+
162
+ eachChild(&:dispose)
163
+ }
164
+ end
165
+ end
166
+
167
+ attr_reader :parent
168
+
169
+ def dispose; Windows.DestroyWindow(@handle) end
170
+
171
+ def windowProc(hwnd, uMsg, wParam, lParam)
172
+ args, result = nil, nil
173
+
174
+ if (handlers = @messages[uMsg])
175
+ args ||= self.class.crackMessage(hwnd, uMsg, wParam, lParam)
176
+
177
+ handlers.each { |handler|
178
+ (handler.arity == 0) ? handler.call : handler.call(args)
179
+
180
+ result = args[:result]; @processed[0], @processed[1] = uMsg, result
181
+ }
182
+ end
183
+
184
+ if uMsg == Windows::WM_COMMAND && (handlers = @commands[Windows.LOWORD(wParam)])
185
+ args ||= self.class.crackMessage(hwnd, uMsg, wParam, lParam)
186
+
187
+ handlers[:all].each { |handler|
188
+ (handler.arity == 0) ? handler.call : handler.call(args)
189
+
190
+ result = args[:result]; @processed[0], @processed[1] = uMsg, result
191
+ } if handlers[:all]
192
+
193
+ handlers[Windows.HIWORD(wParam)].each { |handler|
194
+ (handler.arity == 0) ? handler.call : handler.call(args)
195
+
196
+ result = args[:result]; @processed[0], @processed[1] = uMsg, result
197
+ } if handlers[Windows.HIWORD(wParam)]
198
+ end
199
+
200
+ if uMsg == Windows::WM_NOTIFY && (handlers = @notifies[(nmh = Windows::NMHDR.new(FFI::Pointer.new(lParam)))[:idFrom]])
201
+ args ||= self.class.crackMessage(hwnd, uMsg, wParam, lParam)
202
+
203
+ handlers[:all].each { |handler|
204
+ (handler.arity == 0) ? handler.call : handler.call(args)
205
+
206
+ result = args[:result]; @processed[0], @processed[1] = uMsg, result
207
+ } if handlers[:all]
208
+
209
+ handlers[nmh[:code]].each { |handler|
210
+ (handler.arity == 0) ? handler.call : handler.call(args)
211
+
212
+ result = args[:result]; @processed[0], @processed[1] = uMsg, result
213
+ } if handlers[nmh[:code]]
214
+ end
215
+
216
+ result
217
+ end
218
+
219
+ def onMessage(msg, &block)
220
+ ((@messages ||= {})[Fzeet.constant(msg, :wm_)] ||= []) << block
221
+
222
+ self
223
+ end
224
+
225
+ def onCommand(cmd, notification = :all, &block)
226
+ notification = Fzeet.constant(notification, *self[cmd].class::Prefix[:notification]) unless
227
+ notification.kind_of?(Integer) || notification == :all
228
+
229
+ (((@commands ||= {})[Command[cmd]] ||= {})[notification] ||= []) << block
230
+
231
+ self
232
+ end
233
+
234
+ def onNotify(cmd, notification = :all, &block)
235
+ notification = Fzeet.constant(notification, *self[cmd].class::Prefix[:notification]) unless
236
+ notification.kind_of?(Integer) || notification == :all
237
+
238
+ (((@notifies ||= {})[Command[cmd]] ||= {})[notification] ||= []) << block
239
+
240
+ self
241
+ end
242
+
243
+ def on(*args, &block)
244
+ case args.length
245
+ when 1; onMessage(*args, &block)
246
+ when 2, 3
247
+ case Fzeet.constant(args.shift, :wm_)
248
+ when Windows::WM_COMMAND; onCommand(*args, &block)
249
+ when Windows::WM_NOTIFY; onNotify(*args, &block)
250
+ else raise ArgumentError
251
+ end
252
+ else raise ArgumentError
253
+ end
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,73 @@
1
+ require_relative 'WindowCommon'
2
+
3
+ module Fzeet
4
+ Dialog = BasicWindow['Fzeet.Dialog',
5
+ wndProc: BasicWindow::DialogProc
6
+ ]
7
+
8
+ class Dialog
9
+ def initialize(parent, opts = {}, &block)
10
+ @parent = parent
11
+
12
+ _opts = {
13
+ xstyle: [:noparentnotify],
14
+ caption: Application.name,
15
+ style: [:sysmenu, :visible],
16
+ x: 0,
17
+ y: 0,
18
+ width: 200,
19
+ height: 150,
20
+ modal: false
21
+ }
22
+ badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
23
+ _opts.merge!(opts)
24
+
25
+ _opts[:xstyle] = Fzeet.flags(_opts[:xstyle], *self.class::Prefix[:xstyle])
26
+ _opts[:caption] = _opts[:caption].to_s
27
+ _opts[:style] = Fzeet.flags(_opts[:style], *self.class::Prefix[:style])
28
+
29
+ @messages ||= {}
30
+ @commands ||= {}
31
+ @notifies ||= {}
32
+
33
+ @processed = [0, 0]
34
+
35
+ dt = Windows::DLGTEMPLATE.new
36
+
37
+ dt[:style] = _opts[:style]
38
+ dt[:dwExtendedStyle] = _opts[:xstyle]
39
+ dt[:x] = _opts[:x]
40
+ dt[:y] = _opts[:y]
41
+ dt[:cx] = _opts[:width]
42
+ dt[:cy] = _opts[:height]
43
+
44
+ on(:initdialog) { self.text = _opts[:caption] }
45
+
46
+ on(:initdialog, &block) if block
47
+
48
+ if _opts[:modal]
49
+ @result = Windows.DetonateLastError([-1, 0], :DialogBoxIndirectParam,
50
+ Windows.GetModuleHandle(nil),
51
+ dt,
52
+ @parent && @parent.handle,
53
+ BasicWindow::DialogProc,
54
+ object_id
55
+ )
56
+ else
57
+ @handle = Windows.DetonateLastError(FFI::Pointer::NULL, :CreateDialogIndirectParam,
58
+ Windows.GetModuleHandle(nil),
59
+ dt,
60
+ @parent && @parent.handle,
61
+ BasicWindow::DialogProc,
62
+ object_id
63
+ )
64
+
65
+ self.dialog = true
66
+ end
67
+ end
68
+
69
+ def end(result) Windows.DetonateLastError(0, :EndDialog, @handle, Command[result]); self end
70
+
71
+ def result; DialogResult.new(@result) end
72
+ end
73
+ end
@@ -0,0 +1,13 @@
1
+ require_relative 'WindowCommon'
2
+
3
+ module Fzeet
4
+ Window = BasicWindow['Fzeet.Window']
5
+
6
+ class Window
7
+ def initialize(opts = {})
8
+ (opts[:style] ||= []) << :overlappedwindow << :clipchildren
9
+
10
+ super
11
+ end
12
+ end
13
+ end
data/lib/fzeet/common.rb CHANGED
@@ -16,6 +16,8 @@ module Fzeet
16
16
 
17
17
  Windows.EnableVisualStyles
18
18
 
19
+ Windows.InitializeOle
20
+
19
21
  def constant(c, *prefixes)
20
22
  return c if c.kind_of?(Integer) || c.kind_of?(FFI::Pointer)
21
23
 
@@ -0,0 +1,186 @@
1
+ require_relative 'common'
2
+
3
+ module Fzeet
4
+ module Windows
5
+ ffi_lib 'ole32'
6
+ ffi_convention :stdcall
7
+
8
+ S_OK = 0
9
+
10
+ E_NOTIMPL = 0x80004001 - 0x1_0000_0000
11
+ E_NOINTERFACE = 0x80004002 - 0x1_0000_0000
12
+
13
+ def SUCCEEDED(hr) hr >= 0 end
14
+ def FAILED(hr) hr < 0 end
15
+
16
+ module_function \
17
+ :SUCCEEDED,
18
+ :FAILED
19
+
20
+ class GUID < FFI::Struct
21
+ layout \
22
+ :Data1, :ulong,
23
+ :Data2, :ushort,
24
+ :Data3, :ushort,
25
+ :Data4, [:uchar, 8]
26
+
27
+ def self.[](s)
28
+ raise 'Bad GUID format.' unless s =~ /^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/i
29
+
30
+ new.tap { |guid|
31
+ guid[:Data1] = s[0, 8].to_i(16)
32
+ guid[:Data2] = s[9, 4].to_i(16)
33
+ guid[:Data3] = s[14, 4].to_i(16)
34
+ guid[:Data4][0] = s[19, 2].to_i(16)
35
+ guid[:Data4][1] = s[21, 2].to_i(16)
36
+ s[24, 12].split('').each_slice(2).with_index { |a, i|
37
+ guid[:Data4][i + 2] = a.join('').to_i(16)
38
+ }
39
+ }
40
+ end
41
+ end
42
+
43
+ CLSCTX_INPROC_SERVER = 0x1
44
+
45
+ attach_function :CoCreateInstance, [:pointer, :pointer, :ulong, :pointer, :pointer], :long
46
+
47
+ module COM
48
+ module Interface
49
+ def self.[](*args)
50
+ spec, iid, *ifaces = args.reverse
51
+
52
+ spec.each { |name, signature| signature[0].unshift(:pointer) }
53
+
54
+ Class.new(FFI::Struct) { |iface|
55
+ iface.const_set(:IID, iid)
56
+
57
+ iface.const_set(:VTBL, Class.new(FFI::Struct) { |vtbl|
58
+ vtbl.const_set(:SPEC, Hash[(ifaces.map { |iface| iface::VTBL::SPEC.to_a } << spec.to_a).flatten(1)])
59
+
60
+ vtbl.layout \
61
+ *vtbl::SPEC.map { |name, signature| [name, callback(*signature)] }.flatten
62
+ })
63
+
64
+ iface.layout \
65
+ :lpVtbl, :pointer
66
+ }
67
+ end
68
+ end
69
+
70
+ module Instance
71
+ def self.[](iface)
72
+ Class.new(iface) { |klass|
73
+ def initialize(pointer)
74
+ self.pointer = pointer
75
+
76
+ @vtbl = self.class::VTBL.new(self[:lpVtbl])
77
+ end
78
+
79
+ attr_reader :vtbl
80
+
81
+ VTBL.members.each { |name|
82
+ define_method(name) { |*args|
83
+ raise "#{self}.#{name} failed." if Windows.FAILED(result = @vtbl[name].call(self, *args)); result
84
+ }
85
+ }
86
+ }
87
+ end
88
+ end
89
+
90
+ module Factory
91
+ def self.[](iface, clsid)
92
+ Class.new(iface) { |klass|
93
+ klass.const_set(:CLSID, clsid)
94
+
95
+ def initialize(opts = {})
96
+ @opts = opts
97
+
98
+ @opts[:clsctx] ||= CLSCTX_INPROC_SERVER
99
+
100
+ FFI::MemoryPointer.new(:pointer) { |ppv|
101
+ raise "CoCreateInstance failed (#{self.class})." if
102
+ Windows.FAILED(Windows.CoCreateInstance(self.class::CLSID, nil, @opts[:clsctx], self.class::IID, ppv))
103
+
104
+ self.pointer = ppv.read_pointer
105
+ }
106
+
107
+ @vtbl = self.class::VTBL.new(self[:lpVtbl])
108
+ end
109
+
110
+ attr_reader :vtbl
111
+
112
+ VTBL.members.each { |name|
113
+ define_method(name) { |*args|
114
+ raise "#{self}.#{name} failed." if Windows.FAILED(result = @vtbl[name].call(self, *args)); result
115
+ }
116
+ }
117
+ }
118
+ end
119
+ end
120
+
121
+ module Callback
122
+ def self.[](iface)
123
+ Class.new(iface) { |klass|
124
+ def initialize(opts = {})
125
+ @vtbl, @refc = self.class::VTBL.new, 1
126
+
127
+ @vtbl.members.each { |name|
128
+ @vtbl[name] = instance_variable_set("@fn#{name}",
129
+ FFI::Function.new(*@vtbl.class::SPEC[name].reverse, convention: :stdcall) { |*args|
130
+ send(name, *args[1..-1])
131
+ }
132
+ )
133
+ }
134
+
135
+ self[:lpVtbl] = @vtbl
136
+
137
+ begin
138
+ yield self
139
+ ensure
140
+ Release()
141
+ end if block_given?
142
+ end
143
+
144
+ attr_reader :vtbl, :refc
145
+
146
+ def QueryInterface(riid, ppv)
147
+ if [IID_IUnknown, self.class::IID].any? { |iid| Windows.memcmp(riid, iid, iid.size) == 0 }
148
+ ppv.write_pointer(self)
149
+ else
150
+ ppv.write_pointer(0); return E_NOINTERFACE
151
+ end
152
+
153
+ AddRef(); S_OK
154
+ end
155
+
156
+ def AddRef
157
+ @refc += 1
158
+ end
159
+
160
+ def Release
161
+ @refc -= 1
162
+ end
163
+
164
+ (VTBL.members - IUnknown::VTBL.members).each { |name|
165
+ define_method(name) { |*args|
166
+ E_NOTIMPL
167
+ }
168
+ }
169
+ }
170
+ end
171
+ end
172
+ end
173
+
174
+ IID_IUnknown = GUID['00000000-0000-0000-C000-000000000046']
175
+
176
+ IUnknown = COM::Interface[
177
+ IID_IUnknown,
178
+
179
+ QueryInterface: [[:pointer, :pointer], :long],
180
+ AddRef: [[], :ulong],
181
+ Release: [[], :ulong]
182
+ ]
183
+
184
+ Unknown = COM::Instance[IUnknown]
185
+ end
186
+ end
@@ -1,59 +1 @@
1
- require_relative 'common'
2
-
3
- module Fzeet
4
- module Windows
5
- ffi_lib 'comctl32'
6
- ffi_convention :stdcall
7
-
8
- ICC_LISTVIEW_CLASSES = 0x00000001
9
- ICC_TREEVIEW_CLASSES = 0x00000002
10
- ICC_BAR_CLASSES = 0x00000004
11
- ICC_TAB_CLASSES = 0x00000008
12
- ICC_UPDOWN_CLASS = 0x00000010
13
- ICC_PROGRESS_CLASS = 0x00000020
14
- ICC_HOTKEY_CLASS = 0x00000040
15
- ICC_ANIMATE_CLASS = 0x00000080
16
- ICC_WIN95_CLASSES = 0x000000FF
17
- ICC_DATE_CLASSES = 0x00000100
18
- ICC_USEREX_CLASSES = 0x00000200
19
- ICC_COOL_CLASSES = 0x00000400
20
- ICC_INTERNET_CLASSES = 0x00000800
21
- ICC_PAGESCROLLER_CLASS = 0x00001000
22
- ICC_NATIVEFNTCTL_CLASS = 0x00002000
23
- ICC_STANDARD_CLASSES = 0x00004000
24
- ICC_LINK_CLASS = 0x00008000
25
-
26
- class INITCOMMONCONTROLSEX < FFI::Struct
27
- layout \
28
- :dwSize, :ulong,
29
- :dwICC, :ulong
30
- end
31
-
32
- attach_function :InitCommonControlsEx, [:pointer], :int
33
-
34
- BS_SPLITBUTTON = 0x0000000C
35
- BS_DEFSPLITBUTTON = 0x0000000D
36
- BS_COMMANDLINK = 0x0000000E
37
- BS_DEFCOMMANDLINK = 0x0000000F
38
-
39
- BCM_FIRST = 0x1600
40
- BCM_GETIDEALSIZE = BCM_FIRST + 0x0001
41
- BCM_SETIMAGELIST = BCM_FIRST + 0x0002
42
- BCM_GETIMAGELIST = BCM_FIRST + 0x0003
43
- BCM_SETTEXTMARGIN = BCM_FIRST + 0x0004
44
- BCM_GETTEXTMARGIN = BCM_FIRST + 0x0005
45
- BCM_SETDROPDOWNSTATE = BCM_FIRST + 0x0006
46
- BCM_SETSPLITINFO = BCM_FIRST + 0x0007
47
- BCM_GETSPLITINFO = BCM_FIRST + 0x0008
48
- BCM_SETNOTE = BCM_FIRST + 0x0009
49
- BCM_GETNOTE = BCM_FIRST + 0x000A
50
- BCM_GETNOTELENGTH = BCM_FIRST + 0x000B
51
- BCM_SETSHIELD = BCM_FIRST + 0x000C
52
-
53
- BCN_FIRST = 0x1_0000_0000 - 1250
54
- BCN_LAST = 0x1_0000_0000 - 1350
55
- BCN_HOTITEMCHANGE = BCN_FIRST + 0x0001
56
- BCN_DROPDOWN = BCN_FIRST + 0x0002
57
- NM_GETCUSTOMSPLITRECT = BCN_FIRST + 0x0003
58
- end
59
- end
1
+ require_relative 'comctlbutton'
@@ -0,0 +1,30 @@
1
+ require_relative 'comctlcommon'
2
+
3
+ module Fzeet
4
+ module Windows
5
+ BS_SPLITBUTTON = 0x0000000C
6
+ BS_DEFSPLITBUTTON = 0x0000000D
7
+ BS_COMMANDLINK = 0x0000000E
8
+ BS_DEFCOMMANDLINK = 0x0000000F
9
+
10
+ BCM_FIRST = 0x1600
11
+ BCM_GETIDEALSIZE = BCM_FIRST + 0x0001
12
+ BCM_SETIMAGELIST = BCM_FIRST + 0x0002
13
+ BCM_GETIMAGELIST = BCM_FIRST + 0x0003
14
+ BCM_SETTEXTMARGIN = BCM_FIRST + 0x0004
15
+ BCM_GETTEXTMARGIN = BCM_FIRST + 0x0005
16
+ BCM_SETDROPDOWNSTATE = BCM_FIRST + 0x0006
17
+ BCM_SETSPLITINFO = BCM_FIRST + 0x0007
18
+ BCM_GETSPLITINFO = BCM_FIRST + 0x0008
19
+ BCM_SETNOTE = BCM_FIRST + 0x0009
20
+ BCM_GETNOTE = BCM_FIRST + 0x000A
21
+ BCM_GETNOTELENGTH = BCM_FIRST + 0x000B
22
+ BCM_SETSHIELD = BCM_FIRST + 0x000C
23
+
24
+ BCN_FIRST = 0x1_0000_0000 - 1250
25
+ BCN_LAST = 0x1_0000_0000 - 1350
26
+ BCN_HOTITEMCHANGE = BCN_FIRST + 0x0001
27
+ BCN_DROPDOWN = BCN_FIRST + 0x0002
28
+ NM_GETCUSTOMSPLITRECT = BCN_FIRST + 0x0003
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ require_relative 'common'
2
+
3
+ module Fzeet
4
+ module Windows
5
+ ffi_lib 'comctl32'
6
+ ffi_convention :stdcall
7
+
8
+ ICC_LISTVIEW_CLASSES = 0x00000001
9
+ ICC_TREEVIEW_CLASSES = 0x00000002
10
+ ICC_BAR_CLASSES = 0x00000004
11
+ ICC_TAB_CLASSES = 0x00000008
12
+ ICC_UPDOWN_CLASS = 0x00000010
13
+ ICC_PROGRESS_CLASS = 0x00000020
14
+ ICC_HOTKEY_CLASS = 0x00000040
15
+ ICC_ANIMATE_CLASS = 0x00000080
16
+ ICC_WIN95_CLASSES = 0x000000FF
17
+ ICC_DATE_CLASSES = 0x00000100
18
+ ICC_USEREX_CLASSES = 0x00000200
19
+ ICC_COOL_CLASSES = 0x00000400
20
+ ICC_INTERNET_CLASSES = 0x00000800
21
+ ICC_PAGESCROLLER_CLASS = 0x00001000
22
+ ICC_NATIVEFNTCTL_CLASS = 0x00002000
23
+ ICC_STANDARD_CLASSES = 0x00004000
24
+ ICC_LINK_CLASS = 0x00008000
25
+
26
+ class INITCOMMONCONTROLSEX < FFI::Struct
27
+ layout \
28
+ :dwSize, :ulong,
29
+ :dwICC, :ulong
30
+ end
31
+
32
+ attach_function :InitCommonControlsEx, [:pointer], :int
33
+ end
34
+ end
@@ -0,0 +1 @@
1
+ require_relative 'comdlgofn'
@@ -0,0 +1,9 @@
1
+ require_relative 'common'
2
+
3
+ module Fzeet
4
+ module Windows
5
+ ffi_lib 'comdlg32'
6
+ ffi_convention :stdcall
7
+
8
+ end
9
+ end