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,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'