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
@@ -5,5 +5,5 @@ include Fzeet
5
5
  Application.run { |window| window.dialog = true
6
6
  DateTimePicker.new(window, :datetime1, position: [10, 10, 150, 24])
7
7
 
8
- window[:datetime1].on(:datetimechange) { |args| message args[:st].to_local }
8
+ window[:datetime1].on(:datetimechange) { |args| message args[:st].get }
9
9
  }
@@ -5,5 +5,5 @@ include Fzeet
5
5
  Application.run { |window| window.dialog = true
6
6
  MonthCalendar.new(window, :monthcal1, position: [10, 10, 240, 170])
7
7
 
8
- window[:monthcal1].on(:selchange) { |args| message args[:st1].to_local }
8
+ window[:monthcal1].on(:selchange) { |args| message args[:st1].get }
9
9
  }
@@ -17,9 +17,9 @@ Application.run { |window|
17
17
 
18
18
  (browser = WebBrowser.new(window)).
19
19
  on(:NavigateComplete) { |dispParams|
20
- next if dispParams[:cArgs] < 1 || (arg1 = Windows::VARIANT.new(dispParams[:rgvarg]))[:vt] != Windows::VT_BSTR
20
+ next if dispParams[:cArgs] < 1 || (arg1 = Variant.new(dispParams[:rgvarg]))[:vt] != Windows::VT_BSTR
21
21
 
22
- message Windows.WCSTOMBS(arg1[:bstrVal])
22
+ message arg1.string
23
23
 
24
24
  browser.document.
25
25
  on(:click) { message 'on(:click)' }.
@@ -0,0 +1,24 @@
1
+ require 'fzeet'
2
+
3
+ include Fzeet
4
+
5
+ Application.run { |window|
6
+ (browser = WebBrowser.new(window)).
7
+ on(:NavigateComplete) {
8
+ SafeArray.vector(1) { |sa|
9
+ browser.document.write(sa.put(0, Variant[:bstr, %{
10
+ <!doctype html>
11
+ <html>
12
+ <head>
13
+ <title>Hello</title>
14
+ </head>
15
+ <body>
16
+ <h1>Hello, world!</h1>
17
+ </body>
18
+ </html>
19
+ }]))
20
+ }
21
+ }.
22
+
23
+ goto('about:blank')
24
+ }
@@ -15,7 +15,9 @@ Application.run { |window|
15
15
  (body = all.get('body').get(0)).
16
16
  css(overflow: 'auto').
17
17
  innerHTML = <<-HTML
18
- <button id='button1'>Button1</button> <span id='span1'></span>
18
+ <div>
19
+ <button id='button1'>Button1</button> <span id='span1'></span>
20
+ </div>
19
21
  HTML
20
22
 
21
23
  button1 = nil
@@ -24,7 +26,10 @@ Application.run { |window|
24
26
  on(:readystatechange) {
25
27
  next unless request.readyState == 4
26
28
 
27
- all.get('#span1').innerText = request.responseText if request.status == 200
29
+ all.get('#span1').innerText = case status = request.status
30
+ when 200; request.responseText
31
+ else "Error: status = #{status}"
32
+ end
28
33
 
29
34
  button1.attr(:disabled, false)
30
35
  }
@@ -33,7 +38,7 @@ Application.run { |window|
33
38
  on(:click) {
34
39
  request.
35
40
  open('http://localhost:4567/hello').
36
- send(Windows::VARIANT.new)
41
+ send(Variant.new)
37
42
 
38
43
  button1.attr(:disabled, true)
39
44
  }
@@ -15,7 +15,9 @@ Application.run { |window|
15
15
  (body = all.get('body').get(0)).
16
16
  css(overflow: 'auto').
17
17
  innerHTML = <<-HTML
18
- <button id='button1'>Button1</button> <span id='span1'></span>
18
+ <div>
19
+ <button id='button1'>Button1</button> <span id='span1'></span>
20
+ </div>
19
21
  HTML
20
22
 
21
23
  button1 = nil
@@ -43,7 +45,7 @@ Application.run { |window|
43
45
  on(:click) {
44
46
  xrequest.
45
47
  open('http://localhost:4567/hello').
46
- send(Windows::VARIANT.new)
48
+ send(Variant.new)
47
49
 
48
50
  button1.attr(:disabled, true)
49
51
  }
@@ -0,0 +1,53 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <title>jQueryUI</title>
5
+
6
+ <link rel='stylesheet' href='http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/smoothness/jquery-ui.css' />
7
+
8
+ <style>
9
+ * {
10
+ font-size: small;
11
+ }
12
+
13
+ #themeswitcher {
14
+ float: right;
15
+ }
16
+
17
+ #tabs {
18
+ clear: both;
19
+ }
20
+ </style>
21
+
22
+ <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js'></script>
23
+ <script src='http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js'></script>
24
+
25
+ <script src='http://jqueryui.com/themeroller/themeswitchertool/'></script>
26
+
27
+ <script>
28
+ jQuery(function (j) {
29
+ j('#themeswitcher').themeswitcher({width: 250, height: 600, closeOnSelect: false});
30
+
31
+ j('#tabs').tabs();
32
+ });
33
+ </script>
34
+ </head>
35
+ <body>
36
+ <div id='themeswitcher'></div>
37
+
38
+ <div id='tabs'>
39
+ <ul>
40
+ <li><a id='tab1' href='#page1'>tab1</a></li>
41
+ <li><a id='tab2' href='#page2'>tab2</a></li>
42
+ </ul>
43
+
44
+ <div id='page1'>
45
+ Page1...
46
+ </div>
47
+
48
+ <div id='page2'>
49
+ Page2...
50
+ </div>
51
+ </div>
52
+ </body>
53
+ </html>
@@ -0,0 +1,26 @@
1
+ require 'fzeet'
2
+
3
+ include Fzeet
4
+
5
+ Application.run { |window|
6
+ (browser = WebBrowser.new(window)).
7
+ on(:NavigateComplete) {
8
+ browser.document.on(:ready) {
9
+ all = browser.document.all
10
+
11
+ all.get('html').get(0).
12
+ css(overflow: 'auto')
13
+
14
+ all.get('body').get(0).
15
+ css(overflow: 'auto', margin: '0', padding: '0', background: '#cedefa')
16
+
17
+ (tab1 = all.get('#tab1')).
18
+ on(:click) { message tab1.attr('href').split('#').last }
19
+
20
+ (tab2 = all.get('#tab2')).
21
+ on(:click) { message tab2.attr('href').split('#').last }
22
+ }
23
+ }.
24
+
25
+ goto("file:///#{File.expand_path('jQueryUI.html')}")
26
+ }
data/examples/MDI.rbw CHANGED
@@ -52,7 +52,7 @@ Press Cancel to leave the window open
52
52
  }.
53
53
 
54
54
  on(:command, :open) {
55
- ((Windows::WINVER.AtLeastWindowsVista?) ? ShellFileOpenDialog : FileOpenDialog).new { |dialog|
55
+ ((Windows::Version >= :vista) ? ShellFileOpenDialog : FileOpenDialog).new { |dialog|
56
56
  dialog.multiselect = true
57
57
 
58
58
  next unless dialog.show.ok?
@@ -70,7 +70,7 @@ Press Cancel to leave the window open
70
70
  }.
71
71
 
72
72
  on(:command, :saveAs) {
73
- ((Windows::WINVER.AtLeastWindowsVista?) ? ShellFileSaveDialog : FileSaveDialog).new { |dialog|
73
+ ((Windows::Version >= :vista) ? ShellFileSaveDialog : FileSaveDialog).new { |dialog|
74
74
  next unless dialog.show.ok?
75
75
 
76
76
  child = window.activeChild
@@ -44,8 +44,8 @@ Fzeet::Application.run { |window|
44
44
  UIF.LoadUI(LoadRibbonDll(), "APPLICATION_RIBBON\0".encode('utf-16le'))
45
45
 
46
46
  window.on(:destroy) {
47
- UICH.Release
48
- UIA.Release
49
- UIF.Destroy; UIF.Release
47
+ raise unless UIF.Destroy == S_OK; raise unless UIF.Release == 0
48
+ raise unless UIA.Release == 0
49
+ raise unless UICH.Release == 0
50
50
  }
51
51
  }
@@ -32,8 +32,8 @@ Fzeet::Application.run { |window|
32
32
  UIF.LoadUI(LoadRibbonDll(), "APPLICATION_RIBBON\0".encode('utf-16le'))
33
33
 
34
34
  window.on(:destroy) {
35
- UICH.Release
36
- UIA.Release
37
- UIF.Destroy; UIF.Release
35
+ raise unless UIF.Destroy == S_OK; raise unless UIF.Release == 0
36
+ raise unless UIA.Release == 0
37
+ raise unless UICH.Release == 0
38
38
  }
39
39
  }
data/examples/Version.rbw CHANGED
@@ -5,5 +5,5 @@ include Fzeet
5
5
  message <<-MSG
6
6
  Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}
7
7
 
8
- Windows #{Windows::WINVER}
8
+ Windows #{Windows::Version}
9
9
  MSG
data/lib/fzeet.rb CHANGED
@@ -1,7 +1,22 @@
1
- require_relative 'fzeet/Window'
2
- require_relative 'fzeet/Application'
3
- require_relative 'fzeet/Menu'
4
- require_relative 'fzeet/Accelerator'
5
- require_relative 'fzeet/Control'
6
- require_relative 'fzeet/Dialog'
7
- require_relative 'fzeet/UIRibbon' if Fzeet::Windows::WINVER.AtLeastWindowsVista?
1
+ require_relative 'fzeet/windows'
2
+
3
+ module Fzeet::Windows
4
+ DetonateLastError(0, :InitCommonControlsEx,
5
+ INITCOMMONCONTROLSEX.new.tap { |icc|
6
+ icc[:dwSize] = icc.size
7
+ icc[:dwICC] = \
8
+ ICC_WIN95_CLASSES |
9
+ ICC_DATE_CLASSES |
10
+ ICC_USEREX_CLASSES |
11
+ ICC_COOL_CLASSES |
12
+ ICC_INTERNET_CLASSES |
13
+ ICC_PAGESCROLLER_CLASS
14
+ }
15
+ )
16
+
17
+ EnableVisualStyles()
18
+
19
+ DetonateLastError(0, :SetProcessDPIAware) if Version >= :vista
20
+
21
+ InitializeOle()
22
+ end
data/lib/fzeet/windows.rb CHANGED
@@ -5,23 +5,100 @@ require_relative 'windows/user'
5
5
  require_relative 'windows/gdi'
6
6
 
7
7
  require_relative 'windows/comctl'
8
- require_relative 'windows/scintilla' if Fzeet::Windows::WINVER.AtLeastWindowsXP?
8
+ require_relative 'windows/scintilla' if Fzeet::Windows::Version >= :xp
9
+ #require_relative 'windows/libcef' if Fzeet::Windows::Version >= :xp
9
10
  require_relative 'windows/comdlg'
10
11
 
11
12
  require_relative 'windows/com'
12
13
 
13
14
  require_relative 'windows/ole'
15
+ require_relative 'windows/oleaut'
14
16
  require_relative 'windows/shell'
15
17
  require_relative 'windows/shlwapi'
16
18
  require_relative 'windows/shdocvw'
17
19
  require_relative 'windows/mshtml'
18
20
  require_relative 'windows/urlmon'
19
21
 
20
- require_relative 'windows/propsys' if Fzeet::Windows::WINVER.AtLeastWindowsVista?
22
+ require_relative 'windows/propsys' if Fzeet::Windows::Version >= :vista
21
23
 
22
- require_relative 'windows/uiribbon' if Fzeet::Windows::WINVER.AtLeastWindowsVista?
24
+ require_relative 'windows/uiribbon' if Fzeet::Windows::Version >= :vista
23
25
 
24
26
  Fzeet::Windows.DetonateLastError(FFI::Pointer::NULL,
25
27
  :LoadLibrary,
26
- "#{File.dirname(File.expand_path(__FILE__))}/windows/SciLexer.dll"
27
- ).tap { |hdll| at_exit { Fzeet::Windows.FreeLibrary(hdll) } } if Fzeet::Windows::WINVER.AtLeastWindowsXP?
28
+ "#{File.dirname(File.expand_path(__FILE__))}/windows/scintilla/SciLexer.dll"
29
+ ).tap { |hdll| at_exit { Fzeet::Windows.FreeLibrary(hdll) } } if Fzeet::Windows::Version >= :xp
30
+
31
+ #Fzeet::Windows.DetonateLastError(FFI::Pointer::NULL,
32
+ # :LoadLibrary,
33
+ # "#{File.dirname(File.expand_path(__FILE__))}/windows/libcef/libcef.dll"
34
+ #).tap { |hdll| at_exit { Fzeet::Windows.FreeLibrary(hdll) } } if Fzeet::Windows::Version >= :xp
35
+
36
+ module Fzeet
37
+ class Application
38
+ @name = File.basename($0, '.rbw')
39
+ @version = '0.1.0'
40
+ @authors = []
41
+
42
+ @quitWhenMainWindowCloses = true
43
+
44
+ @window = nil
45
+ @accelerators = []
46
+ @dialogs = []
47
+ @images = {}
48
+ Fzeet.using(ScreenDC.new) { |dc|
49
+ @devcaps = {
50
+ logpixelsy: Windows.GetDeviceCaps(dc.handle, Windows::LOGPIXELSY)
51
+ }
52
+ }
53
+
54
+ class << self
55
+ attr_accessor :name, :version, :authors, :quitWhenMainWindowCloses
56
+ attr_reader :window, :accelerators, :dialogs, :images, :devcaps
57
+ end
58
+
59
+ def self.window=(window)
60
+ raise 'Application.window already set.' if @window
61
+
62
+ @window = window
63
+ end
64
+
65
+ def self.run(windowOrOpts = {}, &block)
66
+ @window = case windowOrOpts
67
+ when BasicWindow; windowOrOpts.tap { |window| block.call(window) if block }
68
+ when Hash
69
+ if windowOrOpts[:deferCreateWindow].tap { windowOrOpts.delete_if { |k, v| k == :deferCreateWindow } }
70
+ Window.new(windowOrOpts, &block)
71
+ else
72
+ Window.new(windowOrOpts).tap { |window| block.call(window) if block }
73
+ end
74
+ else raise ArgumentError
75
+ end
76
+
77
+ return 0 if window.handle.null?
78
+
79
+ @window.on(:destroy) { quit } if @quitWhenMainWindowCloses
80
+
81
+ @window.show.update
82
+
83
+ msg = Message.new
84
+
85
+ while msg.get!
86
+ msg.translate.dispatch unless
87
+ (window.client && Windows.TranslateMDISysAccel(window.client.handle, msg) != 0) ||
88
+ accelerators.any? { |table| table.translate?(msg, @window) } ||
89
+ dialogs.any? { |dialog| dialog.dlgmsg?(msg) }
90
+ end
91
+
92
+ msg[:wParam]
93
+ rescue
94
+ Fzeet.message %Q{#{$!}\n\n#{$!.backtrace.join("\n")}}, icon: :error
95
+ end
96
+
97
+ def self.quit(code = 0)
98
+ accelerators.each(&:dispose)
99
+ images.values.each(&:dispose)
100
+
101
+ Windows.PostQuitMessage(code)
102
+ end
103
+ end
104
+ end
@@ -1,318 +1 @@
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
- S_FALSE = 1
10
-
11
- E_UNEXPECTED = 0x8000FFFF - 0x1_0000_0000
12
- E_NOTIMPL = 0x80004001 - 0x1_0000_0000
13
- E_OUTOFMEMORY = 0x8007000E - 0x1_0000_0000
14
- E_INVALIDARG = 0x80070057 - 0x1_0000_0000
15
- E_NOINTERFACE = 0x80004002 - 0x1_0000_0000
16
- E_POINTER = 0x80004003 - 0x1_0000_0000
17
- E_HANDLE = 0x80070006 - 0x1_0000_0000
18
- E_ABORT = 0x80004004 - 0x1_0000_0000
19
- E_FAIL = 0x80004005 - 0x1_0000_0000
20
- E_ACCESSDENIED = 0x80070005 - 0x1_0000_0000
21
- E_PENDING = 0x8000000A - 0x1_0000_0000
22
-
23
- FACILITY_WIN32 = 7
24
-
25
- ERROR_CANCELLED = 1223
26
-
27
- def SUCCEEDED(hr) hr >= 0 end
28
- def FAILED(hr) hr < 0 end
29
- def HRESULT_FROM_WIN32(x) (x <= 0) ? x : (x & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000 end
30
-
31
- module_function \
32
- :SUCCEEDED,
33
- :FAILED,
34
- :HRESULT_FROM_WIN32
35
-
36
- def DetonateHresult(name, *args)
37
- failed = FAILED(result = send(name, *args)) and raise "#{name} failed (hresult #{format('%#08x', result)})."
38
-
39
- result
40
- ensure
41
- yield failed if block_given?
42
- end
43
-
44
- module_function :DetonateHresult
45
-
46
- class GUID < FFI::Struct
47
- layout \
48
- :Data1, :ulong,
49
- :Data2, :ushort,
50
- :Data3, :ushort,
51
- :Data4, [:uchar, 8]
52
-
53
- def self.[](s)
54
- raise 'Bad GUID format.' unless s =~ /^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/i
55
-
56
- new.tap { |guid|
57
- guid[:Data1] = s[0, 8].to_i(16)
58
- guid[:Data2] = s[9, 4].to_i(16)
59
- guid[:Data3] = s[14, 4].to_i(16)
60
- guid[:Data4][0] = s[19, 2].to_i(16)
61
- guid[:Data4][1] = s[21, 2].to_i(16)
62
- s[24, 12].split('').each_slice(2).with_index { |a, i|
63
- guid[:Data4][i + 2] = a.join('').to_i(16)
64
- }
65
- }
66
- end
67
-
68
- def ==(other) Windows.memcmp(other, self, size) == 0 end
69
- end
70
-
71
- CLSCTX_INPROC_SERVER = 0x1
72
- CLSCTX_INPROC_HANDLER = 0x2
73
- CLSCTX_LOCAL_SERVER = 0x4
74
- CLSCTX_INPROC_SERVER16 = 0x8
75
- CLSCTX_REMOTE_SERVER = 0x10
76
- CLSCTX_INPROC_HANDLER16 = 0x20
77
- CLSCTX_RESERVED1 = 0x40
78
- CLSCTX_RESERVED2 = 0x80
79
- CLSCTX_RESERVED3 = 0x100
80
- CLSCTX_RESERVED4 = 0x200
81
- CLSCTX_NO_CODE_DOWNLOAD = 0x400
82
- CLSCTX_RESERVED5 = 0x800
83
- CLSCTX_NO_CUSTOM_MARSHAL = 0x1000
84
- CLSCTX_ENABLE_CODE_DOWNLOAD = 0x2000
85
- CLSCTX_NO_FAILURE_LOG = 0x4000
86
- CLSCTX_DISABLE_AAA = 0x8000
87
- CLSCTX_ENABLE_AAA = 0x10000
88
- CLSCTX_FROM_DEFAULT_CONTEXT = 0x20000
89
- CLSCTX_ACTIVATE_32_BIT_SERVER = 0x40000
90
- CLSCTX_ACTIVATE_64_BIT_SERVER = 0x80000
91
- CLSCTX_ENABLE_CLOAKING = 0x100000
92
- CLSCTX_PS_DLL = -0x80000000
93
- CLSCTX_INPROC = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER
94
- CLSCTX_ALL = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER
95
- CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER
96
-
97
- attach_function :CoCreateInstance, [:pointer, :pointer, :ulong, :pointer, :pointer], :long
98
-
99
- module COM
100
- module Interface
101
- def self.[](*args)
102
- spec, iid, *ifaces = args.reverse
103
-
104
- spec.each { |name, signature| signature[0].unshift(:pointer) }
105
-
106
- Class.new(FFI::Struct) {
107
- const_set(:IID, iid)
108
-
109
- const_set(:VTBL, Class.new(FFI::Struct) {
110
- const_set(:SPEC, Hash[(ifaces.map { |iface| iface::VTBL::SPEC.to_a } << spec.to_a).flatten(1)])
111
-
112
- layout \
113
- *self::SPEC.map { |name, signature| [name, callback(*signature)] }.flatten
114
- })
115
-
116
- layout \
117
- :lpVtbl, :pointer
118
- }
119
- end
120
- end
121
-
122
- module Helpers
123
- def QueryInstance(klass)
124
- instance = nil
125
-
126
- FFI::MemoryPointer.new(:pointer) { |ppv|
127
- QueryInterface(klass::IID, ppv)
128
-
129
- instance = klass.new(ppv.read_pointer)
130
- }
131
-
132
- begin
133
- yield instance; return self
134
- ensure
135
- instance.Release
136
- end if block_given?
137
-
138
- instance
139
- end
140
-
141
- def UseInstance(klass, name, *args)
142
- instance = nil
143
-
144
- FFI::MemoryPointer.new(:pointer) { |ppv|
145
- send(name, *args, klass::IID, ppv)
146
-
147
- yield instance = klass.new(ppv.read_pointer)
148
- }
149
-
150
- self
151
- ensure
152
- instance.Release if instance
153
- end
154
- end
155
-
156
- module Instance
157
- def self.[](iface)
158
- Class.new(iface) {
159
- send(:include, Helpers)
160
-
161
- def initialize(pointer)
162
- self.pointer = pointer
163
-
164
- @vtbl = self.class::VTBL.new(self[:lpVtbl])
165
- end
166
-
167
- attr_reader :vtbl
168
-
169
- self::VTBL.members.each { |name|
170
- define_method(name) { |*args|
171
- raise "#{self}.#{name} failed." if Windows.FAILED(result = @vtbl[name].call(self, *args)); result
172
- }
173
- }
174
- }
175
- end
176
- end
177
-
178
- module Factory
179
- def self.[](iface, clsid)
180
- Class.new(iface) {
181
- send(:include, Helpers)
182
-
183
- const_set(:CLSID, clsid)
184
-
185
- def initialize(opts = {})
186
- @opts = opts
187
-
188
- @opts[:clsctx] ||= CLSCTX_INPROC_SERVER
189
-
190
- FFI::MemoryPointer.new(:pointer) { |ppv|
191
- raise "CoCreateInstance failed (#{self.class})." if
192
- Windows.FAILED(Windows.CoCreateInstance(self.class::CLSID, nil, @opts[:clsctx], self.class::IID, ppv))
193
-
194
- self.pointer = ppv.read_pointer
195
- }
196
-
197
- @vtbl = self.class::VTBL.new(self[:lpVtbl])
198
- end
199
-
200
- attr_reader :vtbl
201
-
202
- self::VTBL.members.each { |name|
203
- define_method(name) { |*args|
204
- raise "#{self}.#{name} failed." if Windows.FAILED(result = @vtbl[name].call(self, *args)); result
205
- }
206
- }
207
- }
208
- end
209
- end
210
-
211
- module Callback
212
- def self.[](iface)
213
- Class.new(iface) {
214
- send(:include, Helpers)
215
-
216
- def initialize(opts = {})
217
- @vtbl, @refc = self.class::VTBL.new, 1
218
-
219
- @vtbl.members.each { |name|
220
- @vtbl[name] = instance_variable_set("@fn#{name}",
221
- FFI::Function.new(*@vtbl.class::SPEC[name].reverse, convention: :stdcall) { |*args|
222
- send(name, *args[1..-1])
223
- }
224
- )
225
- }
226
-
227
- self[:lpVtbl] = @vtbl
228
-
229
- begin
230
- yield self
231
- ensure
232
- Release()
233
- end if block_given?
234
- end
235
-
236
- attr_reader :vtbl, :refc
237
-
238
- def QueryInterface(riid, ppv)
239
- if [IUnknown::IID, self.class::IID].any? { |iid| Windows.memcmp(riid, iid, iid.size) == 0 }
240
- ppv.write_pointer(self)
241
- else
242
- ppv.write_pointer(0); return E_NOINTERFACE
243
- end
244
-
245
- AddRef(); S_OK
246
- end
247
-
248
- def AddRef
249
- @refc += 1
250
- end
251
-
252
- def Release
253
- @refc -= 1
254
- end
255
-
256
- (self::VTBL.members - IUnknown::VTBL.members).each { |name|
257
- define_method(name) { |*args|
258
- E_NOTIMPL
259
- }
260
- }
261
- }
262
- end
263
- end
264
- end
265
-
266
- IUnknown = COM::Interface[
267
- GUID['00000000-0000-0000-C000-000000000046'],
268
-
269
- QueryInterface: [[:pointer, :pointer], :long],
270
- AddRef: [[], :ulong],
271
- Release: [[], :ulong]
272
- ]
273
-
274
- Unknown = COM::Instance[IUnknown]
275
-
276
- IDispatch = COM::Interface[IUnknown,
277
- GUID['00020400-0000-0000-C000-000000000046'],
278
-
279
- GetTypeInfoCount: [[:pointer], :long],
280
- GetTypeInfo: [[:uint, :ulong, :pointer], :long],
281
- GetIDsOfNames: [[:pointer, :pointer, :uint, :ulong, :pointer], :long],
282
- Invoke: [[:long, :pointer, :ulong, :ushort, :pointer, :pointer, :pointer, :pointer], :long]
283
- ]
284
-
285
- Dispatch = COM::Instance[IDispatch]
286
- DCallback = COM::Callback[IDispatch]
287
-
288
- IConnectionPointContainer = COM::Interface[IUnknown,
289
- GUID['B196B284-BAB4-101A-B69C-00AA00341D07'],
290
-
291
- EnumConnectionPoints: [[:pointer], :long],
292
- FindConnectionPoint: [[:pointer, :pointer], :long]
293
- ]
294
-
295
- ConnectionPointContainer = COM::Instance[IConnectionPointContainer]
296
-
297
- IConnectionPoint = COM::Interface[IUnknown,
298
- GUID['B196B286-BAB4-101A-B69C-00AA00341D07'],
299
-
300
- GetConnectionInterface: [[:pointer], :long],
301
- GetConnectionPointContainer: [[:pointer], :long],
302
- Advise: [[:pointer, :pointer], :long],
303
- Unadvise: [[:ulong], :long],
304
- EnumConnections: [[:pointer], :long]
305
- ]
306
-
307
- ConnectionPoint = COM::Instance[IConnectionPoint]
308
-
309
- IObjectWithSite = COM::Interface[IUnknown,
310
- GUID['FC4801A3-2BA9-11CF-A229-00AA003D7352'],
311
-
312
- SetSite: [[:pointer], :long],
313
- GetSite: [[:pointer, :pointer], :long]
314
- ]
315
-
316
- ObjectWithSite = COM::Callback[IObjectWithSite]
317
- end
318
- end
1
+ require_relative 'com/Common'