fzeet 0.6.5 → 0.6.6

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.
Files changed (140) hide show
  1. data/LICENSE_CEF +29 -0
  2. data/checks/Bstr.rb +14 -0
  3. data/checks/Decimal.rb +27 -0
  4. data/checks/OSVERSIONINFOEX.rb +14 -0
  5. data/checks/Point.rb +65 -0
  6. data/checks/Rect.rb +104 -0
  7. data/checks/RunAll.rb +2 -0
  8. data/checks/SafeArray.rb +27 -0
  9. data/checks/Size.rb +45 -0
  10. data/checks/SystemTime.rb +43 -0
  11. data/checks/Variant.rb +160 -0
  12. data/examples/Control/DateTimePicker.rbw +1 -1
  13. data/examples/Control/MonthCalendar.rbw +1 -1
  14. data/examples/Control/{WebBrowser.rbw → WebBrowser/WebBrowser.rbw} +2 -2
  15. data/examples/Control/{WebBrowser1.rbw → WebBrowser/WebBrowser1.rbw} +0 -0
  16. data/examples/Control/WebBrowser/WebBrowser2.rbw +24 -0
  17. data/examples/Control/{WebBrowser3.rbw → WebBrowser/WebBrowser3.rbw} +0 -0
  18. data/examples/Control/{WebBrowser4.rbw → WebBrowser/WebBrowser4.rbw} +8 -3
  19. data/examples/Control/{WebBrowser4Sinatra.rb → WebBrowser/WebBrowser4Sinatra.rb} +0 -0
  20. data/examples/Control/{WebBrowser5.rbw → WebBrowser/WebBrowser5.rbw} +4 -2
  21. data/examples/Control/WebBrowser/jQueryUI.html +53 -0
  22. data/examples/Control/WebBrowser/jQueryUI.rbw +26 -0
  23. data/examples/MDI.rbw +2 -2
  24. data/examples/Raw/UIRibbon/Command.rbw +3 -3
  25. data/examples/Raw/UIRibbon/Minimal.rbw +3 -3
  26. data/examples/Version.rbw +1 -1
  27. data/lib/fzeet.rb +22 -7
  28. data/lib/fzeet/windows.rb +82 -5
  29. data/lib/fzeet/windows/com.rb +1 -318
  30. data/lib/fzeet/windows/com/Common.rb +318 -0
  31. data/lib/fzeet/windows/comctl.rb +1 -1
  32. data/lib/fzeet/windows/comctl/ComboBoxEx.rb +32 -0
  33. data/lib/fzeet/windows/comctl/DateTimePicker.rb +35 -0
  34. data/lib/fzeet/windows/comctl/Header.rb +61 -1
  35. data/lib/fzeet/windows/comctl/ListView.rb +133 -3
  36. data/lib/fzeet/windows/comctl/MonthCalendar.rb +35 -0
  37. data/lib/fzeet/windows/comctl/ProgressBar.rb +37 -0
  38. data/lib/fzeet/windows/comctl/PropertySheet.rb +50 -2
  39. data/lib/fzeet/windows/comctl/SysLink.rb +37 -0
  40. data/lib/fzeet/windows/comctl/Tab.rb +56 -0
  41. data/lib/fzeet/windows/comctl/TreeView.rb +81 -2
  42. data/lib/fzeet/windows/comctl/UpDown.rb +33 -0
  43. data/lib/fzeet/windows/comdlg.rb +1 -0
  44. data/lib/fzeet/windows/comdlg/ColorDialog.rb +41 -0
  45. data/lib/fzeet/windows/comdlg/Common.rb +87 -0
  46. data/lib/fzeet/windows/comdlg/FileDialog.rb +133 -0
  47. data/lib/fzeet/windows/comdlg/FindReplaceDialog.rb +102 -0
  48. data/lib/fzeet/windows/comdlg/FontDialog.rb +36 -0
  49. data/lib/fzeet/windows/comdlg/PrintDialog.rb +72 -0
  50. data/lib/fzeet/{Dialog → windows/comdlg}/ShellFileDialog.rb +0 -0
  51. data/lib/fzeet/windows/core.rb +5 -0
  52. data/lib/fzeet/windows/core/Common.rb +324 -0
  53. data/lib/fzeet/windows/core/Point.rb +42 -0
  54. data/lib/fzeet/windows/core/Rect.rb +114 -0
  55. data/lib/fzeet/windows/core/Size.rb +34 -0
  56. data/lib/fzeet/windows/core/SystemTime.rb +46 -0
  57. data/lib/fzeet/windows/core/Version.rb +57 -0
  58. data/lib/fzeet/windows/gdi.rb +1 -62
  59. data/lib/fzeet/windows/gdi/Common.rb +40 -0
  60. data/lib/fzeet/windows/gdi/Font.rb +64 -0
  61. data/lib/fzeet/windows/kernel.rb +1 -92
  62. data/lib/fzeet/windows/kernel/Common.rb +92 -0
  63. data/lib/fzeet/windows/libc.rb +1 -1
  64. data/lib/fzeet/windows/libcef.rb +1 -0
  65. data/lib/fzeet/windows/mshtml.rb +1 -1135
  66. data/lib/fzeet/windows/mshtml/Common.rb +1135 -0
  67. data/lib/fzeet/windows/ole.rb +1 -561
  68. data/lib/fzeet/windows/ole/Common.rb +112 -0
  69. data/lib/fzeet/windows/ole/PropVariant.rb +141 -0
  70. data/lib/fzeet/windows/oleaut.rb +3 -0
  71. data/lib/fzeet/windows/oleaut/Bstr.rb +39 -0
  72. data/lib/fzeet/windows/oleaut/Common.rb +187 -0
  73. data/lib/fzeet/windows/oleaut/SafeArray.rb +104 -0
  74. data/lib/fzeet/windows/oleaut/Variant.rb +269 -0
  75. data/lib/fzeet/windows/scintilla.rb +115 -1
  76. data/lib/fzeet/windows/{SciLexer.dll → scintilla/SciLexer.dll} +0 -0
  77. data/lib/fzeet/windows/shdocvw.rb +150 -0
  78. data/lib/fzeet/windows/shell.rb +1 -1
  79. data/lib/fzeet/windows/shell/Common.rb +94 -2
  80. data/lib/fzeet/windows/shlwapi.rb +1 -1
  81. data/lib/fzeet/windows/uiribbon.rb +416 -0
  82. data/lib/fzeet/windows/urlmon.rb +2 -2
  83. data/lib/fzeet/windows/user.rb +20 -0
  84. data/lib/fzeet/windows/user/Accelerator.rb +45 -0
  85. data/lib/fzeet/windows/user/Common.rb +3 -2
  86. data/lib/fzeet/windows/user/Control/Button.rb +54 -0
  87. data/lib/fzeet/windows/user/Control/ComboBox.rb +44 -1
  88. data/lib/fzeet/windows/user/Control/Common.rb +88 -1
  89. data/lib/fzeet/windows/user/Control/Edit.rb +50 -0
  90. data/lib/fzeet/windows/user/Control/ListBox.rb +69 -0
  91. data/lib/fzeet/windows/user/Control/Static.rb +31 -0
  92. data/lib/fzeet/windows/user/Menu.rb +130 -0
  93. data/lib/fzeet/windows/user/Message.rb +9 -0
  94. data/lib/fzeet/windows/user/MessageBox.rb +47 -0
  95. data/lib/fzeet/windows/user/SystemParametersInfo.rb +1 -1
  96. data/lib/fzeet/windows/user/Window.rb +5 -463
  97. data/lib/fzeet/{Window → windows/user/Window}/Common.rb +460 -0
  98. data/lib/fzeet/{Window → windows/user/Window}/Container.rb +0 -0
  99. data/lib/fzeet/{Window → windows/user/Window}/Dialog.rb +0 -0
  100. data/lib/fzeet/{Window → windows/user/Window}/MDI.rb +0 -0
  101. data/lib/fzeet/{Window → windows/user/Window}/View.rb +0 -0
  102. data/lib/fzeet/{Window → windows/user/Window}/Window.rb +0 -0
  103. data/lib/fzeet/{Window → windows/user/Window}/WindowMethods.rb +1 -1
  104. metadata +55 -61
  105. data/examples/Control/WebBrowser2.rbw +0 -39
  106. data/lib/fzeet/Accelerator.rb +0 -48
  107. data/lib/fzeet/Application.rb +0 -71
  108. data/lib/fzeet/Common.rb +0 -350
  109. data/lib/fzeet/Control.rb +0 -19
  110. data/lib/fzeet/Control/Button.rb +0 -57
  111. data/lib/fzeet/Control/ComboBox.rb +0 -46
  112. data/lib/fzeet/Control/ComboBoxEx.rb +0 -35
  113. data/lib/fzeet/Control/Common.rb +0 -89
  114. data/lib/fzeet/Control/DateTimePicker.rb +0 -38
  115. data/lib/fzeet/Control/Edit.rb +0 -53
  116. data/lib/fzeet/Control/ExplorerBrowser.rb +0 -66
  117. data/lib/fzeet/Control/Header.rb +0 -63
  118. data/lib/fzeet/Control/ListBox.rb +0 -72
  119. data/lib/fzeet/Control/ListView.rb +0 -133
  120. data/lib/fzeet/Control/MonthCalendar.rb +0 -38
  121. data/lib/fzeet/Control/ProgressBar.rb +0 -40
  122. data/lib/fzeet/Control/PropertySheet.rb +0 -51
  123. data/lib/fzeet/Control/Scintilla.rb +0 -117
  124. data/lib/fzeet/Control/Static.rb +0 -34
  125. data/lib/fzeet/Control/SysLink.rb +0 -40
  126. data/lib/fzeet/Control/Tab.rb +0 -59
  127. data/lib/fzeet/Control/TreeView.rb +0 -82
  128. data/lib/fzeet/Control/UpDown.rb +0 -36
  129. data/lib/fzeet/Control/WebBrowser.rb +0 -153
  130. data/lib/fzeet/Dialog.rb +0 -6
  131. data/lib/fzeet/Dialog/ColorDialog.rb +0 -44
  132. data/lib/fzeet/Dialog/Common.rb +0 -89
  133. data/lib/fzeet/Dialog/FileDialog.rb +0 -136
  134. data/lib/fzeet/Dialog/FindReplaceDialog.rb +0 -105
  135. data/lib/fzeet/Dialog/FontDialog.rb +0 -39
  136. data/lib/fzeet/Dialog/PrintDialog.rb +0 -75
  137. data/lib/fzeet/Menu.rb +0 -133
  138. data/lib/fzeet/UIRibbon.rb +0 -417
  139. data/lib/fzeet/Window.rb +0 -5
  140. data/lib/fzeet/windows/common.rb +0 -244
@@ -115,4 +115,154 @@ module Fzeet
115
115
 
116
116
  WebBrowser = COM::Factory[IWebBrowser, GUID['EAB22AC3-30C1-11CF-A7EB-0000C05BAE0B']]
117
117
  end
118
+
119
+ class WebBrowser < Windows::WebBrowser
120
+ def initialize(parent)
121
+ @parent = parent
122
+
123
+ @oips = Windows::OleInPlaceSite.new
124
+
125
+ @oips.instance_variable_set(:@browser, self)
126
+
127
+ class << @oips
128
+ attr_reader :browser
129
+
130
+ def CanInPlaceActivate
131
+ Windows::S_OK
132
+ end
133
+
134
+ def GetWindow(phwnd)
135
+ phwnd.write_pointer(browser.parent.handle)
136
+
137
+ Windows::S_OK
138
+ end
139
+
140
+ def GetWindowContext(pframe, pdoc, prPos, prClip, pinfo)
141
+ pframe.write_pointer(0)
142
+ pdoc.write_pointer(0)
143
+ Windows.GetClientRect(browser.parent.handle, prPos)
144
+ Windows.GetClientRect(browser.parent.handle, prClip)
145
+
146
+ Windows::S_OK
147
+ end
148
+
149
+ def OnPosRectChange(prPos)
150
+ browser.QueryInstance(Windows::OleInPlaceObject) { |oipo|
151
+ oipo.SetObjectRects(prPos, prPos)
152
+ }
153
+
154
+ Windows::S_OK
155
+ end
156
+ end
157
+
158
+ @ocs = Windows::OleClientSite.new
159
+
160
+ @ocs.instance_variable_set(:@browser, self)
161
+
162
+ class << @ocs
163
+ attr_reader :browser
164
+
165
+ def QueryInterface(piid, ppv)
166
+ if Windows::GUID.new(piid) == Windows::IOleInPlaceSite::IID
167
+ ppv.write_pointer(browser.oips); browser.oips.AddRef
168
+
169
+ return Windows::S_OK
170
+ end
171
+
172
+ super
173
+ end
174
+ end
175
+
176
+ super()
177
+
178
+ @events = Windows::WebBrowserEvents.new
179
+
180
+ @events.instance_variable_set(:@browser, self)
181
+
182
+ class << @events
183
+ attr_reader :browser
184
+
185
+ (self::VTBL.members - Windows::IDispatch::VTBL.members).each { |name|
186
+ define_method(name) { |dispParams|
187
+ (handlers = browser.handlers && browser.handlers[name]) && handlers.each { |handler|
188
+ (handler.arity == 0) ? handler.call : handler.call(dispParams)
189
+ }
190
+ }
191
+ }
192
+ end
193
+
194
+ QueryInstance(Windows::ConnectionPointContainer) { |cpc|
195
+ FFI::MemoryPointer.new(:pointer) { |pcp|
196
+ cpc.FindConnectionPoint(Windows::WebBrowserEvents::IID, pcp)
197
+
198
+ @cp = Windows::ConnectionPoint.new(pcp.read_pointer)
199
+ }
200
+ }
201
+
202
+ @cookie = nil
203
+ FFI::MemoryPointer.new(:ulong) { |p| @cp.Advise(@events, p); @cookie = p.get_ulong(0) }
204
+
205
+ QueryInstance(Windows::OleObject) { |oo|
206
+ oo.SetClientSite(@ocs)
207
+ oo.DoVerb(Windows::OLEIVERB_INPLACEACTIVATE, nil, @ocs, 0, @parent.handle, @parent.rect)
208
+ }
209
+
210
+ @parent.
211
+ on(:size) {
212
+ r = @parent.rect
213
+
214
+ put_Top(r[:top]); put_Left(r[:left]); put_Width(r[:right]); put_Height(r[:bottom])
215
+ }.
216
+
217
+ on(:destroy) {
218
+ @oips.Release
219
+ @ocs.Release
220
+ @cp.Unadvise(@cookie)
221
+ @events.Release
222
+ @cp.Release
223
+ Release()
224
+ }.
225
+
226
+ instance_variable_set(:@__WebBrowser__, self)
227
+ end
228
+
229
+ attr_reader :parent, :oips, :ocs, :events, :cp, :handlers
230
+
231
+ def on(event, &block)
232
+ ((@handlers ||= {})[event] ||= []) << block
233
+
234
+ self
235
+ end
236
+
237
+ def goto(where)
238
+ where = Windows.SysAllocString("#{where}\0".encode('utf-16le'))
239
+
240
+ Navigate(where, nil, nil, nil, nil)
241
+
242
+ self
243
+ ensure
244
+ Windows.SysFreeString(where)
245
+ end
246
+
247
+ def back; GoBack(); self; rescue; self end
248
+ def forward; GoForward(); self; rescue; self end
249
+ def home; GoHome(); self end
250
+ def search; GoSearch(); self end
251
+
252
+ def refresh; Refresh(); self end
253
+
254
+ def document
255
+ disp = nil
256
+
257
+ FFI::MemoryPointer.new(:pointer) { |pdisp|
258
+ get_Document(pdisp)
259
+
260
+ disp = Windows::Dispatch.new(pdisp.read_pointer)
261
+
262
+ return disp.QueryInstance(Windows::HTMLDocument2)
263
+ }
264
+ ensure
265
+ disp.Release if disp
266
+ end
267
+ end
118
268
  end
@@ -1,2 +1,2 @@
1
1
  require_relative 'shell/BrowseForFolder'
2
- require_relative 'shell/FileDialog' if Fzeet::Windows::WINVER.AtLeastWindowsVista?
2
+ require_relative 'shell/FileDialog' if Fzeet::Windows::Version >= :vista
@@ -6,6 +6,29 @@ module Fzeet
6
6
  ffi_lib 'shell32'
7
7
  ffi_convention :stdcall
8
8
 
9
+ class PROPERTYKEY < FFI::Struct
10
+ layout \
11
+ :fmtid, GUID,
12
+ :pid, :ulong
13
+
14
+ def self.[](type, index)
15
+ new.tap { |key|
16
+ key[:fmtid].tap { |guid|
17
+ guid[:Data1] = 0x00000000 + index
18
+ guid[:Data2] = 0x7363
19
+ guid[:Data3] = 0x696e
20
+ [0x84, 0x41, 0x79, 0x8a, 0xcf, 0x5a, 0xeb, 0xb7].each_with_index { |part, i|
21
+ guid[:Data4][i] = part
22
+ }
23
+ }
24
+
25
+ key[:pid] = type
26
+ }
27
+ end
28
+
29
+ def ==(other) Windows.memcmp(other, self, size) == 0 end
30
+ end
31
+
9
32
  attach_function :ShellExecute, :ShellExecuteA, [:pointer, :string, :string, :string, :string, :int], :pointer
10
33
 
11
34
  attach_function :SHGetPathFromIDList, :SHGetPathFromIDListA, [:pointer, :pointer], :int
@@ -137,7 +160,7 @@ module Fzeet
137
160
 
138
161
  Initialize: [[:pointer, :pointer, :pointer], :long],
139
162
  Destroy: [[], :long],
140
- SetRect: [[:pointer, RECT], :long],
163
+ SetRect: [[:pointer, RECT.by_value], :long],
141
164
  SetPropertyBag: [[:buffer_in], :long],
142
165
  SetEmptyText: [[:buffer_in], :long],
143
166
  SetFolderSettings: [[:pointer], :long],
@@ -257,7 +280,7 @@ module Fzeet
257
280
  FOLDERID_UserPinned = GUID['9e3995ab-1f9c-4f13-b827-48b24b6c7174']
258
281
  FOLDERID_ImplicitAppShortcuts = GUID['bcb5256f-79f6-4cee-b725-dc34e402fd46']
259
282
 
260
- if WINVER.AtLeastWindowsVista?
283
+ if Version >= :vista
261
284
  attach_function :SHGetKnownFolderIDList, [:pointer, :ulong, :pointer, :pointer], :long
262
285
  end
263
286
 
@@ -290,4 +313,73 @@ module Fzeet
290
313
  SBSP_REDIRECT = 0x40000000
291
314
  SBSP_INITIATEDBYHLINKFRAME = 0x80000000
292
315
  end
316
+
317
+ def shell(name, args = nil, dir = nil, verb = 'open')
318
+ raise 'ShellExecute failed.' unless Windows.ShellExecute(nil, verb, name, args, dir, Windows::SW_NORMAL).to_i > 32
319
+ end
320
+
321
+ module_function :shell
322
+
323
+ class ExplorerBrowser < Windows::ExplorerBrowser
324
+ def initialize(parent)
325
+ @parent = parent
326
+
327
+ super()
328
+
329
+ @events = Windows::ExplorerBrowserEvents.new
330
+
331
+ @events.instance_variable_set(:@browser, self)
332
+
333
+ class << @events
334
+ attr_reader :browser
335
+
336
+ (self::VTBL.members - Windows::IUnknown::VTBL.members).each { |name|
337
+ define_method(name) { |*args|
338
+ (handlers = browser.handlers && browser.handlers[name]) && handlers.each { |handler|
339
+ (handler.arity == 0) ? handler.call : handler.call(*args)
340
+ }
341
+
342
+ Windows::S_OK
343
+ }
344
+ }
345
+ end
346
+
347
+ @cookie = nil
348
+ FFI::MemoryPointer.new(:ulong) { |p| Advise(@events, p); @cookie = p.get_ulong(0) }
349
+
350
+ Initialize(@parent.handle, parent.rect, nil)
351
+
352
+ @parent.
353
+ on(:size) { SetRect(nil, @parent.rect) }.
354
+ on(:destroy) { Unadvise(@cookie); @events.Release; Destroy(); Release() }.
355
+
356
+ instance_variable_set(:@__ExplorerBrowser__, self)
357
+ end
358
+
359
+ attr_reader :parent, :events, :handlers
360
+
361
+ def on(event, &block)
362
+ ((@handlers ||= {})["On#{event}".to_sym] ||= []) << block
363
+
364
+ self
365
+ end
366
+
367
+ def goto(where)
368
+ pidl = nil
369
+
370
+ FFI::MemoryPointer.new(:pointer) { |p|
371
+ Windows.SHGetKnownFolderIDList(Windows.const_get("FOLDERID_#{where}"), 0, nil, p)
372
+
373
+ BrowseToIDList(pidl = p.read_pointer, 0)
374
+ }
375
+
376
+ self
377
+ ensure
378
+ Windows.CoTaskMemFree(pidl)
379
+ end
380
+
381
+ def back; BrowseToIDList(nil, Windows::SBSP_NAVIGATEBACK); self end
382
+ def forward; BrowseToIDList(nil, Windows::SBSP_NAVIGATEFORWARD); self end
383
+ def up; BrowseToIDList(nil, Windows::SBSP_PARENT); self end
384
+ end
293
385
  end
@@ -1,4 +1,4 @@
1
- require_relative 'common'
1
+ require_relative 'core'
2
2
 
3
3
  module Fzeet
4
4
  module Windows
@@ -1,4 +1,6 @@
1
1
  require_relative 'ole'
2
+ require_relative 'oleaut'
3
+ require_relative 'shell'
2
4
 
3
5
  module Fzeet
4
6
  module Windows
@@ -385,4 +387,418 @@ module Fzeet
385
387
 
386
388
  module_function :UI_MAKEAPPMODE
387
389
  end
390
+
391
+ class Windows::PropertyStore
392
+ def uiprop(*args)
393
+ args[0] = Windows.const_get("UI_PKEY_#{args[0]}")
394
+
395
+ prop(*args)
396
+ end
397
+
398
+ def update(from)
399
+ case from
400
+ when Windows::LOGFONT
401
+ uiprop(:FontProperties_Family, Windows::PROPVARIANT[:wstring, from.face])
402
+ uiprop(:FontProperties_Size, Windows::PROPVARIANT[:decimal, from.size.round])
403
+ uiprop(:FontProperties_Bold, Windows::PROPVARIANT[:uint, (from.bold?) ? 2 : 1])
404
+ uiprop(:FontProperties_Italic, Windows::PROPVARIANT[:uint, (from.italic?) ? 2 : 1])
405
+ uiprop(:FontProperties_Underline, Windows::PROPVARIANT[:uint, (from.underline?) ? 2 : 1])
406
+ uiprop(:FontProperties_Strikethrough, Windows::PROPVARIANT[:uint, (from.strikeout?) ? 2 : 1])
407
+ else raise ArgumentError
408
+ end
409
+
410
+ self
411
+ end
412
+ end
413
+
414
+ class Windows::UISimplePropertySet
415
+ def get(k) Windows::PROPVARIANT.new.tap { |v| GetValue(k, v) } end
416
+
417
+ def prop(*args)
418
+ case args.length
419
+ when 1; get(*args)
420
+ else raise ArgumentError
421
+ end
422
+ end
423
+
424
+ def uiprop(*args)
425
+ args[0] = Windows.const_get("UI_PKEY_#{args[0]}")
426
+
427
+ prop(*args)
428
+ end
429
+ end
430
+
431
+ class UIRibbon
432
+ class Command
433
+ include Toggle
434
+
435
+ def initialize(ribbon, id)
436
+ @ribbon, @id = ribbon, id
437
+ end
438
+
439
+ attr_reader :ribbon, :id
440
+
441
+ def [](k) Windows::PROPVARIANT.new.tap { |v| ribbon.uif.GetUICommandProperty(id, k, v) } end
442
+ def []=(k, v) ribbon.uif.SetUICommandProperty(id, k, v) end
443
+
444
+ def enabled?; self[Windows::UI_PKEY_Enabled].bool end
445
+ def enabled=(enabled) self[Windows::UI_PKEY_Enabled] = Windows::PROPVARIANT[:bool, enabled] end
446
+
447
+ def checked?; self[Windows::UI_PKEY_BooleanValue].bool end
448
+ def checked=(checked) self[Windows::UI_PKEY_BooleanValue] = Windows::PROPVARIANT[:bool, checked] end
449
+ end
450
+
451
+ def [](id) Command.new(self, id) end
452
+
453
+ module Color
454
+ def self.enhance(hsb, ribbon, method)
455
+ hsb.instance_variable_set(:@ribbon, ribbon)
456
+ hsb.instance_variable_set(:@method, method)
457
+
458
+ class << hsb
459
+ attr_reader :ribbon, :method
460
+
461
+ include Color
462
+ end
463
+
464
+ hsb
465
+ end
466
+
467
+ def darken(amount) self[2] -= amount; ribbon.send("#{method}=", self); self end
468
+ def lighten(amount) self[2] += amount; ribbon.send("#{method}=", self); self end
469
+
470
+ def saturate(amount) self[1] += amount; ribbon.send("#{method}=", self); self end
471
+ def bleach(amount) self[1] -= amount; ribbon.send("#{method}=", self); self end
472
+
473
+ def shift(amount) self[0] += amount; ribbon.send("#{method}=", self); self end
474
+ end
475
+
476
+ def background
477
+ hsb = nil
478
+
479
+ uif.QueryInstance(Windows::PropertyStore) { |ps|
480
+ hsb = ps.uiprop(:GlobalBackgroundColor).uint
481
+ }
482
+
483
+ Color.enhance([Windows::UI_GetHValue(hsb), Windows::UI_GetSValue(hsb), Windows::UI_GetBValue(hsb)], self, __method__)
484
+ end
485
+
486
+ def background=(hsb)
487
+ uif.QueryInstance(Windows::PropertyStore) { |ps|
488
+ ps.uiprop(:GlobalBackgroundColor, Windows::PROPVARIANT[:uint, Windows::UI_HSB(*hsb)]).commit
489
+ }
490
+ end
491
+
492
+ def color
493
+ hsb = nil
494
+
495
+ uif.QueryInstance(Windows::PropertyStore) { |ps|
496
+ hsb = ps.uiprop(:GlobalTextColor).uint
497
+ }
498
+
499
+ Color.enhance([Windows::UI_GetHValue(hsb), Windows::UI_GetSValue(hsb), Windows::UI_GetBValue(hsb)], self, __method__)
500
+ end
501
+
502
+ def color=(hsb)
503
+ uif.QueryInstance(Windows::PropertyStore) { |ps|
504
+ ps.uiprop(:GlobalTextColor, Windows::PROPVARIANT[:uint, Windows::UI_HSB(*hsb)]).commit
505
+ }
506
+ end
507
+
508
+ def highlight
509
+ hsb = nil
510
+
511
+ uif.QueryInstance(Windows::PropertyStore) { |ps|
512
+ hsb = ps.uiprop(:GlobalHighlightColor).uint
513
+ }
514
+
515
+ Color.enhance([Windows::UI_GetHValue(hsb), Windows::UI_GetSValue(hsb), Windows::UI_GetBValue(hsb)], self, __method__)
516
+ end
517
+
518
+ def highlight=(hsb)
519
+ uif.QueryInstance(Windows::PropertyStore) { |ps|
520
+ ps.uiprop(:GlobalHighlightColor, Windows::PROPVARIANT[:uint, Windows::UI_HSB(*hsb)]).commit
521
+ }
522
+ end
523
+
524
+ class GalleryItem < Windows::UISimplePropertySetCallback
525
+ def initialize(label, categoryId = 0, image = nil)
526
+ @label, @categoryId, @image = label, categoryId, image
527
+
528
+ super()
529
+ end
530
+
531
+ attr_reader :label, :categoryId, :image
532
+
533
+ def GetValue(pkey, pvalue)
534
+ key, value = Windows::PROPERTYKEY.new(pkey), Windows::PROPVARIANT.new(pvalue)
535
+
536
+ case key
537
+ when Windows::UI_PKEY_CategoryId
538
+ value.uint = @categoryId; Windows::S_OK
539
+ when Windows::UI_PKEY_Label
540
+ value.wstring = @label; Windows::S_OK
541
+ when Windows::UI_PKEY_ItemImage
542
+ FFI::MemoryPointer.new(:pointer) { |punk|
543
+ Windows::UIImageFromBitmap.new.CreateImage(PARGB32.new(@image).handle, Windows::UI_OWNERSHIP_TRANSFER, punk)
544
+
545
+ unk = Windows::Unknown.new(punk.read_pointer)
546
+ value.unknown = unk
547
+ unk.Release
548
+ }
549
+
550
+ Windows::S_OK
551
+ else
552
+ Windows::E_NOTIMPL
553
+ end
554
+ end
555
+ end
556
+
557
+ def initialize(_window, opts = {})
558
+ handlers = {}
559
+
560
+ opts.delete_if { |k, v|
561
+ next false unless v.kind_of?(Proc)
562
+
563
+ handlers[k] = v; true
564
+ }
565
+
566
+ _opts = {
567
+ name: Application.name,
568
+ resname: 'APPLICATION_RIBBON'
569
+ }
570
+ badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
571
+ _opts.merge!(opts)
572
+
573
+ @creates = []
574
+ @destroys = []
575
+ @sizes = []
576
+ @executesAllVerbs = {}
577
+ @executesExecute = {}
578
+ @executesPreview = {}
579
+ @executesCancelPreview = {}
580
+ @updatesAllKeys = {}
581
+
582
+ @window = _window
583
+
584
+ window.instance_variable_set(:@ribbon, self)
585
+
586
+ class << window
587
+ attr_reader :ribbon
588
+ end
589
+
590
+ @uich = Windows::UICommandHandler.new
591
+
592
+ uich.instance_variable_set(:@ribbon, self)
593
+
594
+ class << uich
595
+ attr_reader :ribbon
596
+
597
+ def Execute(*args) ribbon.execute(*args); Windows::S_OK end
598
+ def UpdateProperty(*args) ribbon.update(*args); Windows::S_OK end
599
+ end
600
+
601
+ @uia = Windows::UIApplication.new
602
+
603
+ uia.instance_variable_set(:@uich, @uich)
604
+
605
+ class << uia
606
+ attr_reader :uich, :uir
607
+
608
+ def OnViewChanged(viewId, typeId, view, verb, reason)
609
+ return Windows::S_OK unless typeId == Windows::UI_VIEWTYPE_RIBBON
610
+
611
+ args = {
612
+ viewId: viewId,
613
+ typeId: typeId,
614
+ view: view,
615
+ verb: verb,
616
+ reason: reason,
617
+ ribbon: self,
618
+ sender: self
619
+ }
620
+
621
+ case verb
622
+ when Windows::UI_VIEWVERB_CREATE
623
+ @uir = Windows::Unknown.new(view).QueryInstance(Windows::UIRibbon)
624
+
625
+ uir.instance_variable_set(:@height, 0)
626
+
627
+ class << uir
628
+ attr_accessor :height
629
+ end
630
+
631
+ uich.ribbon.instance_variable_get(:@creates).each { |handler|
632
+ (handler.arity == 0) ? handler.call : handler.call(args)
633
+ }
634
+ when Windows::UI_VIEWVERB_DESTROY
635
+ uich.ribbon.instance_variable_get(:@destroys).each { |handler|
636
+ (handler.arity == 0) ? handler.call : handler.call(args)
637
+ }
638
+
639
+ uir.Release
640
+ when Windows::UI_VIEWVERB_SIZE
641
+ FFI::MemoryPointer.new(:uint) { |p| uir.GetHeight(p); uir.height = p.read_int }
642
+
643
+ uich.ribbon.instance_variable_get(:@sizes).each { |handler|
644
+ (handler.arity == 0) ? handler.call : handler.call(args)
645
+ }
646
+ end
647
+
648
+ Windows::S_OK
649
+ rescue
650
+ Fzeet.message %Q{#{$!}\n\n#{$!.backtrace.join("\n")}}, icon: :error
651
+
652
+ Windows::S_OK
653
+ end
654
+
655
+ def OnCreateUICommand(*args) uich.QueryInterface(uich.class::IID, args[-1]); Windows::S_OK end
656
+ end
657
+
658
+ @hdll = Windows.LoadRibbonDll(_opts[:name])
659
+
660
+ handlers.each { |k, v|
661
+ k[1] = Object.const_get(k[1]) if k.length > 1
662
+
663
+ on(*k, &v)
664
+ }
665
+
666
+ @uif = Windows::UIFramework.new
667
+
668
+ uif.Initialize(window.handle, uia)
669
+ uif.LoadUI(@hdll, "#{_opts[:resname]}\0".encode('utf-16le'))
670
+
671
+ window.on(:destroy) {
672
+ raise unless uif.Destroy == Windows::S_OK; raise unless uif.Release == 0
673
+ raise unless uia.Release == 0
674
+ raise unless uich.Release == 0
675
+ }
676
+ end
677
+
678
+ attr_reader :hdll, :window, :uich, :uia, :uif
679
+
680
+ def height; uia.uir.height end
681
+
682
+ def execute(commandId, verb, key, value, props)
683
+ args = {
684
+ commandId: commandId,
685
+ verb: verb,
686
+ key: (key.null?) ? nil : Windows::PROPERTYKEY.new(key),
687
+ value: (value.null?) ? nil : Windows::PROPVARIANT.new(value),
688
+ props: (props.null?) ? nil : Windows::UISimplePropertySet.new(props),
689
+ ribbon: self,
690
+ sender: Command.new(self, commandId)
691
+ }
692
+
693
+ (handlers = @executesAllVerbs[commandId]) and handlers.each { |handler|
694
+ (handler.arity == 0) ? handler.call : handler.call(args)
695
+ }
696
+
697
+ case verb
698
+ when Windows::UI_EXECUTIONVERB_EXECUTE
699
+ (handlers = @executesExecute[commandId]) and handlers.each { |handler|
700
+ (handler.arity == 0) ? handler.call : handler.call(args)
701
+ }
702
+ when Windows::UI_EXECUTIONVERB_PREVIEW
703
+ (handlers = @executesPreview[commandId]) and handlers.each { |handler|
704
+ (handler.arity == 0) ? handler.call : handler.call(args)
705
+ }
706
+ when Windows::UI_EXECUTIONVERB_CANCELPREVIEW
707
+ (handlers = @executesCancelPreview[commandId]) and handlers.each { |handler|
708
+ (handler.arity == 0) ? handler.call : handler.call(args)
709
+ }
710
+ end
711
+
712
+ self
713
+ rescue
714
+ Fzeet.message %Q{#{$!}\n\n#{$!.backtrace.join("\n")}}, icon: :error
715
+
716
+ self
717
+ end
718
+
719
+ def update(commandId, key, value, newValue)
720
+ args = {
721
+ commandId: commandId,
722
+ key: (key.null?) ? nil : Windows::PROPERTYKEY.new(key),
723
+ value: (value.null?) ? nil : Windows::PROPVARIANT.new(value),
724
+ newValue: (newValue.null?) ? nil : Windows::PROPVARIANT.new(newValue),
725
+ ribbon: self,
726
+ sender: Command.new(self, commandId)
727
+ }
728
+
729
+ (handlers = @updatesAllKeys[commandId]) and handlers.each { |handler|
730
+ (handler.arity == 0) ? handler.call : handler.call(args)
731
+ }
732
+
733
+ self
734
+ rescue
735
+ Fzeet.message %Q{#{$!}\n\n#{$!.backtrace.join("\n")}}, icon: :error
736
+
737
+ self
738
+ end
739
+
740
+ def invalidate(commandId, flags = Windows::UI_INVALIDATIONS_ALLPROPERTIES, key = nil)
741
+ @uif.InvalidateUICommand(commandId, flags, key)
742
+
743
+ self
744
+ end
745
+
746
+ def on(*args, &block)
747
+ case args.size
748
+ when 1
749
+ case args[0]
750
+ when /^create$/i; @creates << block
751
+ when /^destroy$/i; @destroys << block
752
+ when /^size$/i; @sizes << block
753
+ when Integer; (@executesAllVerbs[args[0]] ||= []) << block
754
+ else raise ArgumentError
755
+ end
756
+ when 2
757
+ case args[0]
758
+ when /^execute$/i; (@executesExecute[args[1]] ||= []) << block
759
+ when /^preview$/i; (@executesPreview[args[1]] ||= []) << block
760
+ when /^cancelpreview$/i; (@executesCancelPreview[args[1]] ||= []) << block
761
+ when /^update$/i; (@updatesAllKeys[args[1]] ||= []) << block
762
+ else raise ArgumentError
763
+ end
764
+ else raise ArgumentError
765
+ end
766
+
767
+ self
768
+ end
769
+
770
+ def fontPropsUpdate(args)
771
+ return self unless args[:key] == Windows::UI_PKEY_FontProperties
772
+
773
+ args[:value].unknown { |current|
774
+ current.QueryInstance(Windows::PropertyStore) { |ps|
775
+ yield ps
776
+
777
+ args[:newValue].unknown = current
778
+ }
779
+ }
780
+
781
+ self
782
+ end
783
+
784
+ def fontPropsChanged(args)
785
+ return self unless args[:key] == Windows::UI_PKEY_FontProperties
786
+
787
+ args[:props].uiprop(:FontProperties_ChangedProperties).unknown { |changed|
788
+ changed.QueryInstance(Windows::PropertyStore) { |ps|
789
+ yield ps
790
+ }
791
+ }
792
+
793
+ self
794
+ end
795
+
796
+ def contextualUI(id, x, y)
797
+ uif.UseInstance(Windows::UIContextualUI, :GetView, id) { |view|
798
+ view.ShowAtLocation(x, y)
799
+ }
800
+
801
+ self
802
+ end
803
+ end
388
804
  end