fzeet 0.4.2 → 0.5.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.
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,64 @@
1
+ require_relative 'WindowMethods'
2
+
3
+ module Fzeet
4
+ class Control < Handle
5
+ include WindowMethods
6
+
7
+ Windows::NONCLIENTMETRICS.new.tap { |ncm|
8
+ ncm[:cbSize] = ncm.size
9
+
10
+ Windows.DetonateLastError(0, :SystemParametersInfo, Windows::SPI_GETNONCLIENTMETRICS, ncm.size, ncm, 0)
11
+
12
+ Font = IndirectFont.new(ncm[:lfMenuFont])
13
+
14
+ at_exit { Font.dispose }
15
+ }
16
+
17
+ def self.crackNotification(args) end
18
+
19
+ def initialize(className, parent, id, opts = {})
20
+ @parent = parent
21
+ @id = Command[id]
22
+
23
+ handlers = {}
24
+
25
+ opts.delete_if { |k, v|
26
+ next false unless v.kind_of?(Proc)
27
+
28
+ handlers[k] = v; true
29
+ }
30
+
31
+ _opts = {
32
+ xstyle: [],
33
+ caption: id.capitalize,
34
+ style: [],
35
+ x: Windows::CW_USEDEFAULT,
36
+ y: Windows::CW_USEDEFAULT,
37
+ width: Windows::CW_USEDEFAULT,
38
+ height: Windows::CW_USEDEFAULT,
39
+ }
40
+ badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
41
+ _opts.merge!(opts)
42
+
43
+ _opts[:xstyle] = Fzeet.flags(_opts[:xstyle], *self.class::Prefix[:xstyle])
44
+ _opts[:caption] = _opts[:caption].to_s
45
+ _opts[:style] = Fzeet.flags([:child, :visible, :tabstop], :ws_) | Fzeet.flags(_opts[:style], *self.class::Prefix[:style])
46
+
47
+ @handle = Windows.DetonateLastError(FFI::Pointer::NULL, :CreateWindowEx,
48
+ _opts[:xstyle], className, _opts[:caption], _opts[:style],
49
+ _opts[:x], _opts[:y], _opts[:width], _opts[:height],
50
+ @parent.handle, FFI::Pointer.new(@id), Windows.GetModuleHandle(nil), nil
51
+ )
52
+
53
+ attach
54
+
55
+ sendmsg(:setfont, Font.handle, 1)
56
+
57
+ handlers.each { |k, v| on(k, &v) }
58
+ end
59
+
60
+ attr_reader :parent, :id
61
+
62
+ def dispose; detach end
63
+ end
64
+ end
@@ -0,0 +1 @@
1
+ require_relative 'DialogFileDialog'
@@ -0,0 +1,5 @@
1
+ require_relative 'WindowDialog'
2
+
3
+ module Fzeet
4
+
5
+ end
@@ -0,0 +1,116 @@
1
+ require_relative 'DialogCommon'
2
+
3
+ module Fzeet
4
+ class FileDialog
5
+ def initialize(opts = {})
6
+ _opts = {
7
+ filter: nil,
8
+ customFilter: nil,
9
+ filterIndex: 0,
10
+ fileTitle: nil,
11
+ initialDir: nil,
12
+ title: nil,
13
+ flags: 0,
14
+ fileExtension: nil,
15
+ defExt: nil,
16
+ custData: 0,
17
+ hook: nil,
18
+ templateName: nil,
19
+ xflags: 0
20
+ }
21
+ badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
22
+ _opts.merge!(opts)
23
+
24
+ @ofn = Windows::OPENFILENAME.new
25
+
26
+ @ofn[:lStructSize] = @ofn.size
27
+ @ofn[:hInstance] = Windows.GetModuleHandle(nil)
28
+ end
29
+
30
+ attr_reader :ofn
31
+
32
+ def path; @path && @path.dup end
33
+ end
34
+
35
+ class OpenFileDialog < FileDialog
36
+ def initialize(opts = {})
37
+ super
38
+ end
39
+
40
+ def show(window = Application.window)
41
+ ofn[:hwndOwner] = window.handle
42
+ ofn[:nMaxFile] = 4096
43
+ ofn[:lpstrFile] = path = FFI::MemoryPointer.new(:char, ofn[:nMaxFile])
44
+
45
+ @path = nil
46
+
47
+ DialogResult.new((Windows.GetOpenFileName(ofn) == 0) ? Windows::IDCANCEL : Windows::IDOK).tap { |result|
48
+ @path = ofn[:lpstrFile].read_string if result.ok?
49
+ }
50
+ ensure
51
+ path.free
52
+ end
53
+ end
54
+
55
+ class SaveFileDialog < FileDialog
56
+ def initialize(opts = {})
57
+ super
58
+ end
59
+
60
+ def show(window = Application.window)
61
+ ofn[:hwndOwner] = window.handle
62
+ ofn[:nMaxFile] = 4096
63
+ ofn[:lpstrFile] = path = FFI::MemoryPointer.new(:char, ofn[:nMaxFile])
64
+
65
+ @path = nil
66
+
67
+ DialogResult.new((Windows.GetSaveFileName(ofn) == 0) ? Windows::IDCANCEL : Windows::IDOK).tap { |result|
68
+ @path = ofn[:lpstrFile].read_string if result.ok?
69
+ }
70
+ ensure
71
+ path.free
72
+ end
73
+ end
74
+
75
+ class FolderDialog
76
+ def initialize(opts = {})
77
+ _opts = {
78
+ root: nil,
79
+ displayName: nil,
80
+ title: nil,
81
+ flags: 0,
82
+ hook: nil,
83
+ param: 0,
84
+ image: 0
85
+ }
86
+ badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
87
+ _opts.merge!(opts)
88
+
89
+ @bi = Windows::BROWSEINFO.new
90
+
91
+ @bi[:ulFlags] = Fzeet.flags([:returnonlyfsdirs, :usenewui], :bif_)
92
+ end
93
+
94
+ attr_reader :bi
95
+
96
+ def path; @path && @path.dup end
97
+
98
+ def show(window = Application.window)
99
+ bi[:hwndOwner] = window.handle
100
+
101
+ @path = nil
102
+
103
+ DialogResult.new(((pidl = Windows.SHBrowseForFolder(bi)).null?) ? Windows::IDCANCEL : Windows::IDOK).tap { |result|
104
+ next unless result.ok?
105
+
106
+ FFI::MemoryPointer.new(:char, 4096) { |p|
107
+ Windows.SHGetPathFromIDList(pidl, p)
108
+
109
+ @path = p.read_string
110
+ }
111
+ }
112
+ ensure
113
+ Windows.CoTaskMemFree(pidl)
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,99 @@
1
+ require_relative 'WindowCommon'
2
+
3
+ module Fzeet
4
+ class UIRibbon
5
+ class Command
6
+ include Toggle
7
+
8
+ def initialize(ribbon, id)
9
+ @ribbon, @id = ribbon, id
10
+ end
11
+
12
+ attr_reader :ribbon, :id
13
+
14
+ def [](k) Windows::PROPVARIANT.new.tap { |v| ribbon.uif.GetUICommandProperty(id, k, v) } end
15
+ def []=(k, v) ribbon.uif.SetUICommandProperty(id, k, v) end
16
+
17
+ def enabled?; self[Windows::UI_PKEY_Enabled].bool end
18
+ def enabled=(enabled) self[Windows::UI_PKEY_Enabled] = Windows::PROPVARIANT[:bool, enabled] end
19
+ end
20
+
21
+ def [](id) Command.new(self, id) end
22
+
23
+ def initialize(window, name = Application.name, resname = 'APPLICATION_RIBBON')
24
+ @executesAllVerbs = {}
25
+
26
+ @window = window
27
+
28
+ @uich = Windows::UICommandHandler.new
29
+
30
+ @uich.instance_variable_set(:@ribbon, self)
31
+
32
+ class << @uich
33
+ attr_reader :ribbon
34
+
35
+ def Execute(*args) @ribbon.execute(*args) end
36
+ end
37
+
38
+ @uia = Windows::UIApplication.new
39
+
40
+ @uia.instance_variable_set(:@uich, @uich)
41
+
42
+ class << @uia
43
+ attr_reader :uich
44
+
45
+ def OnCreateUICommand(*args) @uich.QueryInterface(@uich.class::IID, args[-1]); Windows::S_OK end
46
+ end
47
+
48
+ @uif = Windows::UIFramework.new
49
+
50
+ @uif.Initialize(@window.handle, @uia)
51
+ @uif.LoadUI(@hdll = Windows.LoadRibbonDll(name), "#{resname}\0".encode('utf-16le'))
52
+
53
+ @window.on(:destroy) {
54
+ @uich.Release
55
+ @uia.Release
56
+ @uif.Destroy; @uif.Release
57
+ }
58
+ end
59
+
60
+ attr_reader :window, :uich, :uia, :uif
61
+
62
+ def execute(commandId, verb, key, value, props)
63
+ args = {
64
+ commandId: commandId,
65
+ ribbon: self,
66
+ sender: Command.new(self, commandId)
67
+ }
68
+
69
+ result = Windows::E_NOTIMPL
70
+
71
+ begin
72
+ if @executesAllVerbs.include?(commandId)
73
+ @executesAllVerbs[commandId].each { |handler|
74
+ (handler.arity == 0) ? handler.call : handler.call(args)
75
+ }
76
+
77
+ result = Windows::S_OK
78
+ end
79
+ rescue
80
+ Fzeet.message %Q{#{$!}\n\n#{$!.backtrace.join("\n")}}, icon: :error
81
+ end
82
+
83
+ result
84
+ end
85
+
86
+ def on(*args, &block)
87
+ case args.size
88
+ when 1
89
+ case args[0]
90
+ when Integer; (@executesAllVerbs[args[0]] ||= []) << block
91
+ else raise ArgumentError
92
+ end
93
+ else raise ArgumentError
94
+ end
95
+
96
+ self
97
+ end
98
+ end
99
+ end
data/lib/fzeet/Window.rb CHANGED
@@ -1,336 +1,2 @@
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
-
257
- Window = BasicWindow['Fzeet.Window']
258
-
259
- class Window
260
- def initialize(opts = {})
261
- (opts[:style] ||= []) << :overlappedwindow << :clipchildren
262
-
263
- super
264
- end
265
- end
266
-
267
- Dialog = BasicWindow['Fzeet.Dialog',
268
- wndProc: BasicWindow::DialogProc
269
- ]
270
-
271
- class Dialog
272
- def initialize(parent, opts = {}, &block)
273
- @parent = parent
274
-
275
- _opts = {
276
- xstyle: [:noparentnotify],
277
- caption: Application.name,
278
- style: [:sysmenu, :visible],
279
- x: 0,
280
- y: 0,
281
- width: 200,
282
- height: 150,
283
- modal: false
284
- }
285
- badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
286
- _opts.merge!(opts)
287
-
288
- _opts[:xstyle] = Fzeet.flags(_opts[:xstyle], *self.class::Prefix[:xstyle])
289
- _opts[:caption] = _opts[:caption].to_s
290
- _opts[:style] = Fzeet.flags(_opts[:style], *self.class::Prefix[:style])
291
-
292
- @messages ||= {}
293
- @commands ||= {}
294
- @notifies ||= {}
295
-
296
- @processed = [0, 0]
297
-
298
- dt = Windows::DLGTEMPLATE.new
299
-
300
- dt[:style] = _opts[:style]
301
- dt[:dwExtendedStyle] = _opts[:xstyle]
302
- dt[:x] = _opts[:x]
303
- dt[:y] = _opts[:y]
304
- dt[:cx] = _opts[:width]
305
- dt[:cy] = _opts[:height]
306
-
307
- on(:initdialog) { self.text = _opts[:caption] }
308
-
309
- on(:initdialog, &block) if block
310
-
311
- if _opts[:modal]
312
- @result = Windows.DetonateLastError([-1, 0], :DialogBoxIndirectParam,
313
- Windows.GetModuleHandle(nil),
314
- dt,
315
- @parent && @parent.handle,
316
- BasicWindow::DialogProc,
317
- object_id
318
- )
319
- else
320
- @handle = Windows.DetonateLastError(FFI::Pointer::NULL, :CreateDialogIndirectParam,
321
- Windows.GetModuleHandle(nil),
322
- dt,
323
- @parent && @parent.handle,
324
- BasicWindow::DialogProc,
325
- object_id
326
- )
327
-
328
- self.dialog = true
329
- end
330
- end
331
-
332
- def end(result) Windows.DetonateLastError(0, :EndDialog, @handle, Command[result]); self end
333
-
334
- def result; DialogResult.new(@result) end
335
- end
336
- end
1
+ require_relative 'WindowWindow'
2
+ require_relative 'WindowDialog'