fzeet 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/examples/Dialog/ColorDialog.rbw +21 -0
  2. data/examples/Dialog/FileDialog.rbw +47 -0
  3. data/examples/Dialog/FindReplaceDialog.rbw +38 -0
  4. data/examples/Dialog/FontDialog.rbw +33 -0
  5. data/examples/Dialog/PrintDialog.rbw +31 -0
  6. data/examples/Dialog/ShellFileDialog.rbw +43 -0
  7. data/examples/Version.rbw +5 -1
  8. data/lib/fzeet/Common.rb +6 -1
  9. data/lib/fzeet/Dialog/ColorDialog.rb +44 -0
  10. data/lib/fzeet/Dialog/Common.rb +84 -0
  11. data/lib/fzeet/Dialog/FileDialog.rb +83 -27
  12. data/lib/fzeet/Dialog/FindReplaceDialog.rb +105 -0
  13. data/lib/fzeet/Dialog/FontDialog.rb +39 -0
  14. data/lib/fzeet/Dialog/PrintDialog.rb +75 -0
  15. data/lib/fzeet/Dialog/ShellFileDialog.rb +133 -0
  16. data/lib/fzeet/Dialog.rb +5 -1
  17. data/lib/fzeet/windows/com.rb +16 -1
  18. data/lib/fzeet/windows/comdlg/ColorDialog.rb +34 -0
  19. data/lib/fzeet/windows/comdlg/Common.rb +37 -1
  20. data/lib/fzeet/windows/comdlg/FileDialog.rb +37 -0
  21. data/lib/fzeet/windows/comdlg/FindReplaceDialog.rb +50 -0
  22. data/lib/fzeet/windows/comdlg/FontDialog.rb +78 -0
  23. data/lib/fzeet/windows/comdlg/PrintDialog.rb +198 -0
  24. data/lib/fzeet/windows/comdlg.rb +4 -0
  25. data/lib/fzeet/windows/gdi.rb +3 -0
  26. data/lib/fzeet/windows/shell/{FolderDialog.rb → BrowseForFolder.rb} +11 -0
  27. data/lib/fzeet/windows/shell/Common.rb +56 -0
  28. data/lib/fzeet/windows/shell/FileDialog.rb +78 -0
  29. data/lib/fzeet/windows/shell.rb +2 -1
  30. data/lib/fzeet/windows/user/Message.rb +1 -0
  31. data/lib/fzeet/windows.rb +1 -0
  32. metadata +24 -6
  33. data/examples/Dialog/FileAndFolderDialog.rbw +0 -34
  34. data/lib/fzeet/Dialog/FolderDialog.rb +0 -45
@@ -0,0 +1,21 @@
1
+ require 'fzeet'
2
+
3
+ include Fzeet
4
+
5
+ Application.run { |window|
6
+ dialog = ColorDialog.new
7
+
8
+ dialog.on(:initdialog) { message 'on(:initdialog)' }
9
+
10
+ window.menu = Menu.new.
11
+ append(:popup, '&View', PopupMenu.new.
12
+ append(:string, '&Color...', :color)
13
+ )
14
+
15
+ window.
16
+ on(:command, :color) {
17
+ message dialog.color if dialog.show.ok?
18
+ }.
19
+
20
+ on(:destroy) { dialog.dispose }
21
+ }
@@ -0,0 +1,47 @@
1
+ require 'fzeet'
2
+
3
+ include Fzeet
4
+
5
+ Application.run { |window|
6
+ window.menu = Menu.new.
7
+ append(:popup, '&File', PopupMenu.new.
8
+ append(:string, '&Open...', :open).
9
+ append(:string, 'Open &Multiple...', :openMultiple).
10
+ append(:string, 'Save &As...', :saveAs).
11
+
12
+ append(:separator).
13
+
14
+ append(:string, 'Browse For &Folder...', :browseForFolder)
15
+ )
16
+
17
+ window.
18
+ on(:command, :open) {
19
+ FileOpenDialog.new { |dialog|
20
+ dialog.on(:initdialog) { message 'on(:initdialog)' }
21
+
22
+ message dialog.path if dialog.show.ok?
23
+ }
24
+ }.
25
+
26
+ on(:command, :openMultiple) {
27
+ FileOpenDialog.new(flags: :allowmultiselect) { |dialog|
28
+ message dialog.paths.join("\n") if dialog.show.ok?
29
+ }
30
+ }.
31
+
32
+ on(:command, :saveAs) {
33
+ FileSaveDialog.new { |dialog|
34
+ dialog.on(:initdialog) { message 'on(:initdialog)' }
35
+
36
+ message dialog.path if dialog.show.ok?
37
+ }
38
+ }.
39
+
40
+ on(:command, :browseForFolder) {
41
+ dialog = FolderDialog.new
42
+
43
+ dialog.on(Windows::BFFM_IUNKNOWN) { message 'Windows::BFFM_IUNKNOWN' }
44
+
45
+ message dialog.path if dialog.show.ok?
46
+ }
47
+ }
@@ -0,0 +1,38 @@
1
+ require 'fzeet'
2
+
3
+ include Fzeet
4
+
5
+ Application.run { |window|
6
+ window.menu = Menu.new.
7
+ append(:popup, '&Edit', PopupMenu.new.
8
+ append(:string, '&Find...', :find).
9
+ append(:string, '&Replace...', :replace)
10
+ )
11
+
12
+ window.
13
+ on(:command, :find) {
14
+ dialog = FindDialog.new
15
+
16
+ dialog.on(:initdialog) { |args| message 'on(:initdialog)'; args[:result] = 1 }
17
+
18
+ dialog.show.
19
+ onNotify(:findnext) { message "on(:findnext) - #{dialog.findWhat}" }.
20
+ onNotify(:dialogterm) { [:find, :replace].each { |id| window.menu[id].enabled = true } }
21
+
22
+ [:find, :replace].each { |id| window.menu[id].enabled = false }
23
+ }.
24
+
25
+ on(:command, :replace) {
26
+ dialog = ReplaceDialog.new
27
+
28
+ dialog.on(:initdialog) { |args| message 'on(:initdialog)'; args[:result] = 1 }
29
+
30
+ dialog.show.
31
+ onNotify(:findnext) { message "on(:findnext) - #{dialog.findWhat}" }.
32
+ onNotify(:replace) { message "on(:replace) - #{dialog.findWhat} with #{dialog.replaceWith}" }.
33
+ onNotify(:replaceall) { message "on(:replaceall) - #{dialog.findWhat} with #{dialog.replaceWith}" }.
34
+ onNotify(:dialogterm) { [:find, :replace].each { |id| window.menu[id].enabled = true } }
35
+
36
+ [:find, :replace].each { |id| window.menu[id].enabled = false }
37
+ }
38
+ }
@@ -0,0 +1,33 @@
1
+ require 'fzeet'
2
+
3
+ include Fzeet
4
+
5
+ Application.run(View.new) { |window|
6
+ font = IndirectFont.new(Control::Font.logfont)
7
+ color = 0
8
+
9
+ window.menu = Menu.new.
10
+ append(:popup, '&View', PopupMenu.new.
11
+ append(:string, '&Font...', :font)
12
+ )
13
+
14
+ window.
15
+ on(:command, :font) {
16
+ dialog = FontDialog.new(font: font, color: color)
17
+
18
+ dialog.on(:initdialog) { message 'on(:initdialog)' }
19
+
20
+ next unless dialog.show.ok?
21
+
22
+ font.dispose; font = dialog.font; color = dialog.color
23
+
24
+ window.invalidate
25
+ }.
26
+
27
+ on(:paint) { window.paint { |dc| dc.select(font) {
28
+ dc.color = color
29
+ dc.sms 'The quick brown fox jumps over the lazy dog. 1234567890'
30
+ }}}.
31
+
32
+ on(:destroy) { font.dispose }
33
+ }
@@ -0,0 +1,31 @@
1
+ require 'fzeet'
2
+
3
+ include Fzeet
4
+
5
+ Application.run { |window|
6
+ window.menu = Menu.new.
7
+ append(:popup, '&File', PopupMenu.new.
8
+ append(:string, 'Page Set&up...', :pageSetup).
9
+ append(:string, '&Print...', :print).
10
+ append(:string, 'P&rint1...', :print1)
11
+ )
12
+
13
+ window.
14
+ on(:command, :pageSetup) {
15
+ dialog = PageSetupDialog.new
16
+
17
+ message dialog.show.ok?
18
+ }.
19
+
20
+ on(:command, :print) {
21
+ dialog = PrintDialog.new
22
+
23
+ message dialog.show.ok?
24
+ }.
25
+
26
+ on(:command, :print1) {
27
+ dialog = PrintDialogEx.new
28
+
29
+ message dialog.show.ok?
30
+ }
31
+ }
@@ -0,0 +1,43 @@
1
+ require 'fzeet'
2
+
3
+ include Fzeet
4
+
5
+ Application.run { |window|
6
+ window.menu = Menu.new.
7
+ append(:popup, '&File', PopupMenu.new.
8
+ append(:string, '&Open...', :open).
9
+ append(:string, 'Open &Multiple...', :openMultiple).
10
+ append(:string, 'Save &As...', :saveAs).
11
+
12
+ append(:separator).
13
+
14
+ append(:string, 'Select &Folder...', :selectFolder)
15
+ )
16
+
17
+ window.
18
+ on(:command, :open) {
19
+ ShellFileOpenDialog.new { |dialog|
20
+ message dialog.path if dialog.show.ok?
21
+ }
22
+ }.
23
+
24
+ on(:command, :openMultiple) {
25
+ ShellFileOpenDialog.new { |dialog|
26
+ dialog.SetOptions(Windows::FOS_ALLOWMULTISELECT)
27
+
28
+ message dialog.paths.join("\n") if dialog.show.ok?
29
+ }
30
+ }.
31
+
32
+ on(:command, :saveAs) {
33
+ ShellFileSaveDialog.new { |dialog|
34
+ message dialog.path if dialog.show.ok?
35
+ }
36
+ }.
37
+
38
+ on(:command, :selectFolder) {
39
+ ShellFolderDialog.new { |dialog|
40
+ message dialog.path if dialog.show.ok?
41
+ }
42
+ }
43
+ }
data/examples/Version.rbw CHANGED
@@ -2,4 +2,8 @@ require 'fzeet'
2
2
 
3
3
  include Fzeet
4
4
 
5
- message Windows::WINVER
5
+ message <<-MSG
6
+ Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}
7
+
8
+ Windows #{Windows::WINVER}
9
+ MSG
data/lib/fzeet/Common.rb CHANGED
@@ -166,7 +166,7 @@ module Fzeet
166
166
  @@instances = {}
167
167
 
168
168
  def self.instance?(handle) @@instances.include?(handle.to_i) end
169
- def self.instance(handle) raise "#{self}.instance failed." unless (instance = @@instances[handle.to_i]); instance end
169
+ def self.instance(handle) raise "#{self}.#{__method__} failed." unless (instance = @@instances[handle.to_i]); instance end
170
170
 
171
171
  def self.wrap(handle, iface)
172
172
  Object.new.tap { |o|
@@ -180,6 +180,8 @@ module Fzeet
180
180
 
181
181
  def attach; @@instances[@handle.to_i] = self end
182
182
  def detach; @@instances.delete(@handle.to_i) end
183
+
184
+ def dup; raise "#{self}.#{__method__} is not implemented." end
183
185
  end
184
186
 
185
187
  def using(o, cleanup = :dispose)
@@ -294,6 +296,9 @@ module Fzeet
294
296
  holds.each { |hold| Windows.SelectObject(@handle, hold) }
295
297
  end
296
298
 
299
+ def color; Windows.GetTextColor(@handle) end
300
+ def color=(color) Windows.SetTextColor(@handle, color) end
301
+
297
302
  def fillRect(rect, brush) Windows.DetonateLastError(0, :FillRect, @handle, rect, brush.handle); self end
298
303
 
299
304
  def text(text, rect, flags = 0) Windows.DetonateLastError(0, :DrawText, @handle, text, -1, rect, Fzeet.flags(flags, :dt_)); self end
@@ -0,0 +1,44 @@
1
+ require_relative 'Common'
2
+
3
+ module Fzeet
4
+ class ColorDialog < CommonDialog
5
+ DialogStruct = Windows::CHOOSECOLOR
6
+
7
+ HookProc = -> *args { CommonDialog::HookProc.(*args.unshift(DialogStruct)) }
8
+
9
+ def initialize(opts = {})
10
+ _opts = {
11
+
12
+ }
13
+ badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
14
+ _opts.merge!(opts)
15
+
16
+ @struct = DialogStruct.new
17
+
18
+ @struct[:lStructSize] = @struct.size
19
+ @struct[:hInstance] = Windows.GetModuleHandle(nil)
20
+ @struct[:lpCustColors] = @buf = FFI::MemoryPointer.new(:ulong, 16)
21
+ @struct[:Flags] = Fzeet.flags(:enablehook, :cc_)
22
+ @struct[:lCustData] = object_id
23
+ @struct[:lpfnHook] = HookProc
24
+
25
+ super()
26
+
27
+ begin
28
+ yield self
29
+ ensure
30
+ dispose
31
+ end if block_given?
32
+ end
33
+
34
+ def dispose; @buf.free end
35
+
36
+ def show(window = Application.window)
37
+ @struct[:hwndOwner] = window.handle
38
+
39
+ DialogResult.new((Windows.ChooseColor(@struct) == 0) ? Windows::IDCANCEL : Windows::IDOK)
40
+ end
41
+
42
+ def color; result = @struct[:rgbResult]; [Windows.GetRValue(result), Windows.GetBValue(result), Windows.GetBValue(result)] end
43
+ end
44
+ end
@@ -1,5 +1,89 @@
1
1
  require_relative '../Window/Dialog'
2
2
 
3
3
  module Fzeet
4
+ class CommonDialog < Handle
5
+ include WindowMethods
4
6
 
7
+ HookProc = -> klass, hwnd, uMsg, wParam, lParam {
8
+ begin
9
+ if klass == Windows::BROWSEINFO
10
+ if uMsg == Windows::BFFM_IUNKNOWN
11
+ instance = ObjectSpace._id2ref(lParam)
12
+
13
+ if @@instances.include?(hwnd.to_i)
14
+ @@instances.delete(hwnd.to_i)
15
+ else
16
+ @@instances[hwnd.to_i] = instance
17
+
18
+ @@instances[hwnd.to_i].instance_variable_set(:@handle, hwnd)
19
+ end
20
+ end
21
+ else
22
+ if uMsg == Windows::WM_INITDIALOG
23
+ @@instances[hwnd.to_i] = ObjectSpace._id2ref(
24
+ klass.new(FFI::Pointer.new(lParam))[:lCustData].to_i
25
+ )
26
+
27
+ @@instances[hwnd.to_i].instance_variable_set(:@handle, hwnd)
28
+ end
29
+ end
30
+
31
+ result = @@instances[hwnd.to_i].hookProc(hwnd, uMsg, wParam, lParam) if @@instances[hwnd.to_i]
32
+ rescue
33
+ answer = Fzeet.message %Q{#{$!}\n\n#{$!.backtrace.join("\n")}}, buttons: [:abort, :retry, :ignore], icon: :error
34
+
35
+ Application.quit if answer.abort?
36
+ ensure
37
+ if uMsg == Windows::WM_NCDESTROY
38
+ @@instances.delete(hwnd.to_i)
39
+ end
40
+ end
41
+
42
+ result || 0
43
+ }
44
+
45
+ def self.crackMessage(hwnd, uMsg, wParam, lParam)
46
+ window = @@instances[hwnd.to_i]
47
+
48
+ args = {
49
+ hwnd: hwnd,
50
+ uMsg: uMsg,
51
+ wParam: wParam,
52
+ lParam: lParam,
53
+ result: 0,
54
+ window: window,
55
+ sender: window
56
+ }
57
+
58
+ args
59
+ end
60
+
61
+ def initialize
62
+ @messages = {}
63
+ end
64
+
65
+ attr_reader :struct
66
+
67
+ def hookProc(hwnd, uMsg, wParam, lParam)
68
+ args, result = nil, nil
69
+
70
+ if (handlers = @messages[uMsg])
71
+ args ||= self.class.crackMessage(hwnd, uMsg, wParam, lParam)
72
+
73
+ handlers.each { |handler|
74
+ (handler.arity == 0) ? handler.call : handler.call(args)
75
+
76
+ result = args[:result]
77
+ }
78
+ end
79
+
80
+ result
81
+ end
82
+
83
+ def on(msg, &block)
84
+ (@messages[Fzeet.constant(msg, :wm_)] ||= []) << block
85
+
86
+ self
87
+ end
88
+ end
5
89
  end
@@ -1,7 +1,11 @@
1
1
  require_relative 'Common'
2
2
 
3
3
  module Fzeet
4
- class FileDialog
4
+ class FileDialog < CommonDialog
5
+ DialogStruct = Windows::OPENFILENAME
6
+
7
+ HookProc = -> *args { CommonDialog::HookProc.(*args.unshift(DialogStruct)) }
8
+
5
9
  def initialize(opts = {})
6
10
  _opts = {
7
11
  filter: nil,
@@ -21,54 +25,106 @@ module Fzeet
21
25
  badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
22
26
  _opts.merge!(opts)
23
27
 
24
- @ofn = Windows::OPENFILENAME.new
28
+ @struct = DialogStruct.new
29
+
30
+ @struct[:lStructSize] = @struct.size
31
+ @struct[:hInstance] = Windows.GetModuleHandle(nil)
32
+ @struct[:lpstrFile] = @buf = FFI::MemoryPointer.new(:char, 4096)
33
+ @struct[:nMaxFile] = @buf.size
34
+ @struct[:Flags] = Fzeet.flags([:enablehook, :explorer, :enablesizing] + [*_opts[:flags]], :ofn_)
35
+ @struct[:lCustData] = object_id
36
+ @struct[:lpfnHook] = HookProc
25
37
 
26
- @ofn[:lStructSize] = @ofn.size
27
- @ofn[:hInstance] = Windows.GetModuleHandle(nil)
38
+ super()
39
+
40
+ begin
41
+ yield self
42
+ ensure
43
+ dispose
44
+ end if block_given?
28
45
  end
29
46
 
30
- attr_reader :ofn
47
+ def dispose; @buf.free end
31
48
 
32
- def path; @path && @path.dup end
49
+ def path; @buf.read_string end
33
50
  end
34
51
 
35
- class OpenFileDialog < FileDialog
36
- def initialize(opts = {})
37
- super
52
+ class FileOpenDialog < FileDialog
53
+ def show(window = Application.window)
54
+ @struct[:hwndOwner] = window.handle
55
+
56
+ DialogResult.new((Windows.GetOpenFileName(@struct) == 0) ? Windows::IDCANCEL : Windows::IDOK)
38
57
  end
39
58
 
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])
59
+ def paths
60
+ return [path] if
61
+ (path = @buf.read_string).length + 1 != @struct[:nFileOffset]
44
62
 
45
- @path = nil
63
+ result, tip = [], path.length + 1
46
64
 
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
65
+ until @buf.get_bytes(tip, 2) == "\0\0"
66
+ result << (name = @buf.get_string(tip))
67
+
68
+ tip += name.length + 1
69
+ end
70
+
71
+ result.map! { |name| "#{path}\\#{name}" }
52
72
  end
53
73
  end
54
74
 
55
- class SaveFileDialog < FileDialog
75
+ class FileSaveDialog < FileDialog
76
+ def show(window = Application.window)
77
+ @struct[:hwndOwner] = window.handle
78
+
79
+ DialogResult.new((Windows.GetSaveFileName(@struct) == 0) ? Windows::IDCANCEL : Windows::IDOK)
80
+ end
81
+ end
82
+
83
+ class FolderDialog < CommonDialog
84
+ DialogStruct = Windows::BROWSEINFO
85
+
86
+ HookProc = -> *args { CommonDialog::HookProc.(*args.unshift(DialogStruct)) }
87
+
56
88
  def initialize(opts = {})
57
- super
89
+ _opts = {
90
+ root: nil,
91
+ displayName: nil,
92
+ title: nil,
93
+ flags: 0,
94
+ hook: nil,
95
+ param: 0,
96
+ image: 0
97
+ }
98
+ badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
99
+ _opts.merge!(opts)
100
+
101
+ @struct = DialogStruct.new
102
+
103
+ @struct[:ulFlags] = Fzeet.flags([:returnonlyfsdirs, :usenewui], :bif_)
104
+ @struct[:lpfn] = HookProc
105
+ @struct[:lParam] = object_id
106
+
107
+ super()
58
108
  end
59
109
 
110
+ def path; @path && @path.dup end
111
+
60
112
  def show(window = Application.window)
61
- ofn[:hwndOwner] = window.handle
62
- ofn[:nMaxFile] = 4096
63
- ofn[:lpstrFile] = path = FFI::MemoryPointer.new(:char, ofn[:nMaxFile])
113
+ @struct[:hwndOwner] = window.handle
64
114
 
65
115
  @path = nil
66
116
 
67
- DialogResult.new((Windows.GetSaveFileName(ofn) == 0) ? Windows::IDCANCEL : Windows::IDOK).tap { |result|
68
- @path = ofn[:lpstrFile].read_string if result.ok?
117
+ DialogResult.new(((pidl = Windows.SHBrowseForFolder(@struct)).null?) ? Windows::IDCANCEL : Windows::IDOK).tap { |result|
118
+ next unless result.ok?
119
+
120
+ FFI::MemoryPointer.new(:char, 4096) { |p|
121
+ Windows.SHGetPathFromIDList(pidl, p)
122
+
123
+ @path = p.read_string
124
+ }
69
125
  }
70
126
  ensure
71
- path.free
127
+ Windows.CoTaskMemFree(pidl)
72
128
  end
73
129
  end
74
130
  end
@@ -0,0 +1,105 @@
1
+ require_relative 'Common'
2
+
3
+ module Fzeet
4
+ class FindReplaceDialog < CommonDialog
5
+ DialogStruct = Windows::FINDREPLACE
6
+
7
+ HookProc = -> *args { CommonDialog::HookProc.(*args.unshift(DialogStruct)) }
8
+
9
+ Message = Windows.DetonateLastError(0, :RegisterWindowMessage, Windows::FINDMSGSTRING)
10
+
11
+ def initialize(opts = {})
12
+ _opts = {
13
+
14
+ }
15
+ badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
16
+ _opts.merge!(opts)
17
+
18
+ @frNotifies = {}
19
+
20
+ @struct = DialogStruct.new
21
+
22
+ @struct[:lStructSize] = @struct.size
23
+ @struct[:hInstance] = Windows.GetModuleHandle(nil)
24
+ @struct[:Flags] = Fzeet.flags(:enablehook, :fr_)
25
+ @struct[:lpstrFindWhat] = @findbuf = FFI::MemoryPointer.new(:char, 4096)
26
+ @struct[:lpstrReplaceWith] = @replacebuf = FFI::MemoryPointer.new(:char, 4096)
27
+ @struct[:wFindWhatLen] = @findbuf.size
28
+ @struct[:wReplaceWithLen] = @replacebuf.size
29
+ @struct[:lCustData] = object_id
30
+ @struct[:lpfnHook] = HookProc
31
+
32
+ super()
33
+ end
34
+
35
+ def dispose; [@findbuf, @replacebuf].each(&:free) end
36
+
37
+ def findWhat; @findbuf.read_string end
38
+ def replaceWith; @replacebuf.read_string end
39
+
40
+ def frProc(args)
41
+ return unless args[:lParam] == @struct.pointer.address
42
+
43
+ (handlers = @frNotifies[:all]) and handlers.each { |handler|
44
+ (handler.arity == 0) ? handler.call : handler.call(args)
45
+ }
46
+
47
+ if @struct[:Flags] & Windows::FR_DIALOGTERM != 0
48
+ (handlers = @frNotifies[Windows::FR_DIALOGTERM]) and handlers.each { |handler|
49
+ (handler.arity == 0) ? handler.call : handler.call(args)
50
+ }
51
+
52
+ self.dialog = false
53
+
54
+ dispose
55
+ elsif @struct[:Flags] & Windows::FR_FINDNEXT != 0
56
+ (handlers = @frNotifies[Windows::FR_FINDNEXT]) and handlers.each { |handler|
57
+ (handler.arity == 0) ? handler.call : handler.call(args)
58
+ }
59
+ elsif @struct[:Flags] & Windows::FR_REPLACE != 0
60
+ (handlers = @frNotifies[Windows::FR_REPLACE]) and handlers.each { |handler|
61
+ (handler.arity == 0) ? handler.call : handler.call(args)
62
+ }
63
+ elsif @struct[:Flags] & Windows::FR_REPLACEALL != 0
64
+ (handlers = @frNotifies[Windows::FR_REPLACEALL]) and handlers.each { |handler|
65
+ (handler.arity == 0) ? handler.call : handler.call(args)
66
+ }
67
+ end
68
+ end
69
+
70
+ def onNotify(notification, &block)
71
+ notification = Fzeet.constant(notification, :fr_) unless
72
+ notification.kind_of?(Integer) || notification == :all
73
+
74
+ (@frNotifies[notification] ||= []) << block
75
+
76
+ self
77
+ end
78
+ end
79
+
80
+ class FindDialog < FindReplaceDialog
81
+ def show(window = Application.window)
82
+ @struct[:hwndOwner] = window.handle
83
+ @handle = Windows.DetonateLastError(FFI::Pointer::NULL, :FindText, @struct)
84
+
85
+ self.dialog = true
86
+
87
+ window.on(FindReplaceDialog::Message, &method(:frProc))
88
+
89
+ self
90
+ end
91
+ end
92
+
93
+ class ReplaceDialog < FindReplaceDialog
94
+ def show(window = Application.window)
95
+ @struct[:hwndOwner] = window.handle
96
+ @handle = Windows.DetonateLastError(FFI::Pointer::NULL, :ReplaceText, @struct)
97
+
98
+ self.dialog = true
99
+
100
+ window.on(FindReplaceDialog::Message, &method(:frProc))
101
+
102
+ self
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,39 @@
1
+ require_relative 'Common'
2
+
3
+ module Fzeet
4
+ class FontDialog < CommonDialog
5
+ DialogStruct = Windows::CHOOSEFONT
6
+
7
+ HookProc = -> *args { CommonDialog::HookProc.(*args.unshift(DialogStruct)) }
8
+
9
+ def initialize(opts = {})
10
+ _opts = {
11
+ font: Control::Font,
12
+ color: 0
13
+ }
14
+ badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
15
+ _opts.merge!(opts)
16
+
17
+ @struct = DialogStruct.new
18
+
19
+ @struct[:lStructSize] = @struct.size
20
+ @struct[:hInstance] = Windows.GetModuleHandle(nil)
21
+ @struct[:lpLogFont] = _opts[:font].logfont.pointer
22
+ @struct[:Flags] = Fzeet.flags([:enablehook, :both, :inittologfontstruct, :effects], :cf_)
23
+ @struct[:rgbColors] = _opts[:color]
24
+ @struct[:lCustData] = object_id
25
+ @struct[:lpfnHook] = HookProc
26
+
27
+ super()
28
+ end
29
+
30
+ def show(window = Application.window)
31
+ @struct[:hwndOwner] = window.handle
32
+
33
+ DialogResult.new((Windows.ChooseFont(@struct) == 0) ? Windows::IDCANCEL : Windows::IDOK)
34
+ end
35
+
36
+ def font; IndirectFont.new(Windows::LOGFONT.new(@struct[:lpLogFont])) end
37
+ def color; @struct[:rgbColors] end
38
+ end
39
+ end