fzeet 0.6.3 → 0.6.4

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.
@@ -0,0 +1,32 @@
1
+ require 'fzeet'
2
+
3
+ include Fzeet
4
+
5
+ Application.run { |window|
6
+ window.menu = Menu.new.
7
+ append(:popup, '&Go To', PopupMenu.new.
8
+ append(:string, '&Back', :back).
9
+ append(:string, '&Forward', :forward).
10
+ append(:string, '&Up', :up)
11
+ )
12
+
13
+ (browser = ExplorerBrowser.new(window)).
14
+ SetOptions(Windows::EBO_SHOWFRAMES)
15
+
16
+ def (browser.events).OnNavigationComplete(pidl)
17
+ FFI::MemoryPointer.new(:char, 4096) { |p|
18
+ Windows.SHGetPathFromIDList(pidl, p)
19
+
20
+ message p.read_string
21
+ }
22
+
23
+ Windows::S_OK
24
+ end
25
+
26
+ browser.goto(:Desktop)
27
+
28
+ window.
29
+ on(:command, :back, &browser.method(:back)).
30
+ on(:command, :forward, &browser.method(:forward)).
31
+ on(:command, :up, &browser.method(:up))
32
+ }
@@ -0,0 +1,33 @@
1
+ require 'fzeet'
2
+
3
+ include Fzeet
4
+
5
+ Application.run { |window|
6
+ window.menu = Menu.new.
7
+ append(:popup, '&View', PopupMenu.new.
8
+ append(:string, '&Refresh', :refresh)
9
+ ).
10
+
11
+ append(:popup, '&Go To', PopupMenu.new.
12
+ append(:string, '&Back', :back).
13
+ append(:string, '&Forward', :forward).
14
+ append(:string, '&Home', :home).
15
+ append(:string, '&Search', :search)
16
+ )
17
+
18
+ browser = WebBrowser.new(window)
19
+
20
+ def (browser.events).NavigateComplete(url)
21
+ message Windows.WCSTOMBS(url)
22
+ end
23
+
24
+ browser.search
25
+
26
+ window.
27
+ on(:command, :refresh, &browser.method(:refresh)).
28
+
29
+ on(:command, :back, &browser.method(:back)).
30
+ on(:command, :forward, &browser.method(:forward)).
31
+ on(:command, :home, &browser.method(:home)).
32
+ on(:command, :search, &browser.method(:search))
33
+ }
@@ -24,7 +24,9 @@ Application.run { |window|
24
24
  }.
25
25
 
26
26
  on(:command, :openMultiple) {
27
- FileOpenDialog.new(flags: :allowmultiselect) { |dialog|
27
+ FileOpenDialog.new { |dialog|
28
+ dialog.multiselect = true
29
+
28
30
  message dialog.paths.join("\n") if dialog.show.ok?
29
31
  }
30
32
  }.
data/examples/MDI.rbw CHANGED
@@ -3,28 +3,130 @@ require 'fzeet'
3
3
  include Fzeet
4
4
 
5
5
  Application.run(Frame.new) { |window|
6
- children, total = [], 0
7
-
8
6
  window.menu.
9
7
  append(:popup, '&File', PopupMenu.new.
10
- append(:string, '&New', :new)
8
+ append(:string, "&New\tCtrl+N", :new).
9
+ append(:string, "&Open...\tCtrl+O", :open).
10
+ append(:string, "&Save\tCtrl+S", :save).
11
+ append(:string, "Save &As...\tCtrl+Shift+S", :saveAs)
11
12
  )
12
13
 
14
+ Application.accelerators << AcceleratorTable.new(
15
+ [:control, :n, :new],
16
+ [:control, :o, :open],
17
+ [:control, :s, :save],
18
+ [[:control, :shift], :s, :saveAs]
19
+ )
20
+
13
21
  window.
14
22
  on(:command, :new) {
15
- children << MDIChild.new(window.client, caption: "Child#{total += 1}").
16
- on(:close) { |args|
17
- args[:result] = nil if args[:sender].question('Close?', buttons: [:yes, :No]).yes?
18
- }.
23
+ child = MDIChild.new(window.client, caption: 'Untitled')
24
+
25
+ Scintilla.new(child, :sci, style: :border, position: child.rect.to_a, anchor: :ltrb)
26
+
27
+ child[:sci].focus = true
28
+
29
+ child[:sci].font = 'Courier New'
30
+ child[:sci].fontSize = 10
31
+
32
+ child[:sci].tabWidth = 2
33
+
34
+ child.on(:close) { |args|
35
+ if args[:sender][:sci].dirty?
36
+ answer = args[:sender].question(%Q{
37
+ File not saved:
38
+ #{args[:sender].text}
39
+
40
+ Press Yes to save it and close the window
41
+ Press No to close the window without saving
42
+ Press Cancel to leave the window open
43
+ }, buttons: [:yes, :no, :Cancel], icon: :warning)
44
+
45
+ window.sendmsg(:command, Command[:save]) if answer.yes?
46
+
47
+ args[:result] = nil unless answer.cancel?
48
+ else
49
+ args[:result] = nil
50
+ end
51
+ }
52
+ }.
53
+
54
+ on(:command, :open) {
55
+ ((Windows::WINVER.AtLeastWindowsVista?) ? ShellFileOpenDialog : FileOpenDialog).new { |dialog|
56
+ dialog.multiselect = true
57
+
58
+ next unless dialog.show.ok?
59
+
60
+ dialog.paths.each { |path|
61
+ window.sendmsg(:command, Command[:new])
19
62
 
20
- on(:destroy) { |args| children.delete(args[:sender]) }
63
+ child = window.activeChild
64
+
65
+ child.text, child[:sci].text = path, File.read(path)
66
+
67
+ child[:sci].toggle(:dirty).sendmsg(:emptyundobuffer)
68
+ }
69
+ }
70
+ }.
71
+
72
+ on(:command, :saveAs) {
73
+ ((Windows::WINVER.AtLeastWindowsVista?) ? ShellFileSaveDialog : FileSaveDialog).new { |dialog|
74
+ next unless dialog.show.ok?
75
+
76
+ child = window.activeChild
77
+
78
+ File.open(child.text = dialog.path, 'w') { |f| f << child[:sci].text; child[:sci].dirty = false }
79
+ }
80
+ }.
81
+
82
+ on(:command, :save) {
83
+ child = window.activeChild
84
+
85
+ (child.text == 'Untitled') ?
86
+ window.sendmsg(:command, Command[:saveAs]) :
87
+ File.open(child.text, 'w') { |f| f << child[:sci].text; child[:sci].dirty = false }
88
+ }.
89
+
90
+ on(:command, :saveAll) {
91
+ window.client.eachChild { |child|
92
+ next unless child.kind_of?(MDIChild)
93
+
94
+ window.
95
+ activate(child).
96
+ sendmsg(:command, Command[:save])
97
+ }
98
+ }.
99
+
100
+ on(:initmenupopup) {
101
+ child = window.activeChild
102
+
103
+ [:save, :saveAs].each { |command| window.menu[command].enabled = !child.nil? }
21
104
  }.
22
105
 
23
106
  on(:close) {
107
+ dirties = []
108
+
24
109
  window.client.eachChild { |child|
25
- # Ask each child if it's ok to close
110
+ next unless child.kind_of?(MDIChild)
111
+
112
+ dirties << child if child[:sci].dirty?
26
113
  }
27
114
 
28
- window.dispose
115
+ if dirties.length > 0
116
+ answer = window.question(%Q{
117
+ File#{(dirties.length > 1) ? 's' : ''} not saved:
118
+ #{dirties.map(&:text).join("\n ")}
119
+
120
+ Press Yes to save #{(dirties.length > 1) ? 'them' : 'it'} and close the application
121
+ Press No to close the application without saving
122
+ Press Cancel to leave the application open
123
+ }, buttons: [:yes, :no, :Cancel], icon: :warning)
124
+
125
+ window.sendmsg(:command, Command[:saveAll]) if answer.yes?
126
+
127
+ window.dispose unless answer.cancel?
128
+ else
129
+ window.dispose
130
+ end
29
131
  }
30
132
  }
@@ -2,44 +2,44 @@ require 'fzeet'
2
2
 
3
3
  include Fzeet::Windows
4
4
 
5
- def onItem1(*args)
6
- Fzeet.message __method__
5
+ Fzeet::Application.run { |window|
6
+ def onItem1(*args)
7
+ Fzeet.message __method__
7
8
 
8
- UIF.SetUICommandProperty(CmdButton1, UI_PKEY_Enabled, PROPVARIANT[:bool, true])
9
- UIF.SetUICommandProperty(CmdItem1, UI_PKEY_Enabled, PROPVARIANT[:bool, false])
10
- end
9
+ UIF.SetUICommandProperty(CmdButton1, UI_PKEY_Enabled, PROPVARIANT[:bool, true])
10
+ UIF.SetUICommandProperty(CmdItem1, UI_PKEY_Enabled, PROPVARIANT[:bool, false])
11
+ end
11
12
 
12
- def onButton1(*args)
13
- Fzeet.message __method__
13
+ def onButton1(*args)
14
+ Fzeet.message __method__
14
15
 
15
- UIF.SetUICommandProperty(CmdItem1, UI_PKEY_Enabled, PROPVARIANT[:bool, true])
16
- UIF.SetUICommandProperty(CmdButton1, UI_PKEY_Enabled, PROPVARIANT[:bool, false])
17
- end
16
+ UIF.SetUICommandProperty(CmdItem1, UI_PKEY_Enabled, PROPVARIANT[:bool, true])
17
+ UIF.SetUICommandProperty(CmdButton1, UI_PKEY_Enabled, PROPVARIANT[:bool, false])
18
+ end
18
19
 
19
- UICH = UICommandHandler.new
20
+ UICH = UICommandHandler.new
20
21
 
21
- def UICH.Execute(*args)
22
- case args[0]
23
- when CmdItem1
24
- onItem1(*args)
25
- when CmdButton1
26
- onButton1(*args)
27
- end
22
+ def UICH.Execute(*args)
23
+ case args[0]
24
+ when CmdItem1
25
+ onItem1(*args)
26
+ when CmdButton1
27
+ onButton1(*args)
28
+ end
28
29
 
29
- S_OK
30
- end
30
+ S_OK
31
+ end
31
32
 
32
- UIA = UIApplication.new
33
+ UIA = UIApplication.new
33
34
 
34
- def UIA.OnCreateUICommand(*args)
35
- UICH.QueryInterface(UICH.class::IID, args[-1])
35
+ def UIA.OnCreateUICommand(*args)
36
+ UICH.QueryInterface(UICH.class::IID, args[-1])
36
37
 
37
- S_OK
38
- end
38
+ S_OK
39
+ end
39
40
 
40
- UIF = UIFramework.new
41
+ UIF = UIFramework.new
41
42
 
42
- Fzeet::Application.run { |window|
43
43
  UIF.Initialize(window.handle, UIA)
44
44
  UIF.LoadUI(LoadRibbonDll(), "APPLICATION_RIBBON\0".encode('utf-16le'))
45
45
 
@@ -2,32 +2,32 @@ require 'fzeet'
2
2
 
3
3
  include Fzeet::Windows
4
4
 
5
- def onButton1(*args)
6
- Fzeet.message __method__
7
- end
5
+ Fzeet::Application.run { |window|
6
+ def onButton1(*args)
7
+ Fzeet.message __method__
8
+ end
8
9
 
9
- UICH = UICommandHandler.new
10
+ UICH = UICommandHandler.new
10
11
 
11
- def UICH.Execute(*args)
12
- case args[0]
13
- when CmdButton1
14
- onButton1(*args)
15
- end
12
+ def UICH.Execute(*args)
13
+ case args[0]
14
+ when CmdButton1
15
+ onButton1(*args)
16
+ end
16
17
 
17
- S_OK
18
- end
18
+ S_OK
19
+ end
19
20
 
20
- UIA = UIApplication.new
21
+ UIA = UIApplication.new
21
22
 
22
- def UIA.OnCreateUICommand(*args)
23
- UICH.QueryInterface(UICH.class::IID, args[-1])
23
+ def UIA.OnCreateUICommand(*args)
24
+ UICH.QueryInterface(UICH.class::IID, args[-1])
24
25
 
25
- S_OK
26
- end
26
+ S_OK
27
+ end
27
28
 
28
- UIF = UIFramework.new
29
+ UIF = UIFramework.new
29
30
 
30
- Fzeet::Application.run { |window|
31
31
  UIF.Initialize(window.handle, UIA)
32
32
  UIF.LoadUI(LoadRibbonDll(), "APPLICATION_RIBBON\0".encode('utf-16le'))
33
33
 
@@ -60,9 +60,24 @@ module Fzeet
60
60
  handlers.each { |k, v| on(k, &v) }
61
61
 
62
62
  case _opts[:anchor]
63
- when :ltr; @parent.on(:size) { self.position = @parent.rect.tap { |r| r[:bottom] = _opts[:height] }.to_a }
64
- when :lrb; @parent.on(:size) { self.position = @parent.rect.tap { |r| r[:top] = r[:bottom] - _opts[:height]; r[:bottom] = _opts[:height] }.to_a }
65
- when :ltrb; @parent.on(:size) { self.position = @parent.rect.to_a }
63
+ when :ltr
64
+ @parent.on(:size) { |args|
65
+ self.position = @parent.rect.tap { |r| r[:bottom] = _opts[:height] }.to_a
66
+
67
+ args[:result] = nil if @parent.class == MDIChild
68
+ }
69
+ when :lrb
70
+ @parent.on(:size) { |args|
71
+ self.position = @parent.rect.tap { |r| r[:top] = r[:bottom] - _opts[:height]; r[:bottom] = _opts[:height] }.to_a
72
+
73
+ args[:result] = nil if @parent.class == MDIChild
74
+ }
75
+ when :ltrb
76
+ @parent.on(:size) { |args|
77
+ self.position = @parent.rect.to_a
78
+
79
+ args[:result] = nil if @parent.class == MDIChild
80
+ }
66
81
  else raise ArgumentError, "Bad anchor spec: #{_opts[:anchor]}."
67
82
  end if _opts[:anchor]
68
83
  end
@@ -0,0 +1,66 @@
1
+ require_relative 'Common'
2
+
3
+ module Fzeet
4
+ class ExplorerBrowser < Windows::ExplorerBrowser
5
+ def initialize(parent)
6
+ @parent = parent
7
+
8
+ super()
9
+
10
+ @events = Windows::ExplorerBrowserEvents.new
11
+
12
+ @events.instance_variable_set(:@browser, self)
13
+
14
+ class << @events
15
+ attr_reader :browser
16
+
17
+ def OnNavigationPending(*args)
18
+ Windows::S_OK
19
+ end
20
+
21
+ def OnViewCreated(*args)
22
+ Windows::S_OK
23
+ end
24
+
25
+ def OnNavigationComplete(*args)
26
+ Windows::S_OK
27
+ end
28
+
29
+ def OnNavigationFailed(*args)
30
+ Windows::S_OK
31
+ end
32
+ end
33
+
34
+ @cookie = nil
35
+ FFI::MemoryPointer.new(:ulong) { |p| Advise(@events, p); @cookie = p.get_ulong(0) }
36
+
37
+ Initialize(@parent.handle, parent.rect, nil)
38
+
39
+ @parent.
40
+ on(:size) { SetRect(nil, @parent.rect) }.
41
+ on(:destroy) { Unadvise(@cookie); @events.Release; Destroy(); Release() }.
42
+
43
+ instance_variable_set(:@__ExplorerBrowser__, self)
44
+ end
45
+
46
+ attr_reader :parent, :events
47
+
48
+ def goto(where)
49
+ pidl = nil
50
+
51
+ FFI::MemoryPointer.new(:pointer) { |p|
52
+ Windows.SHGetKnownFolderIDList(Windows.const_get("FOLDERID_#{where}"), 0, nil, p)
53
+
54
+ BrowseToIDList(pidl = p.read_pointer, 0)
55
+ }
56
+
57
+ self
58
+ ensure
59
+ Windows.CoTaskMemFree(pidl)
60
+ end
61
+
62
+ def back; BrowseToIDList(nil, Windows::SBSP_NAVIGATEBACK); self end
63
+ def forward; BrowseToIDList(nil, Windows::SBSP_NAVIGATEFORWARD); self end
64
+ def up; BrowseToIDList(nil, Windows::SBSP_PARENT); self end
65
+ end
66
+ end
@@ -39,6 +39,9 @@ module Fzeet
39
39
 
40
40
  def tabWidth; sendmsg(:gettabwidth) end
41
41
  def tabWidth=(tabWidth) sendmsg(:settabwidth, tabWidth) end
42
+
43
+ def dirty?; @dirty end
44
+ def dirty=(dirty) (dirty) ? @dirty = true : sendmsg(:setsavepoint) end
42
45
  end
43
46
 
44
47
  class Scintilla < Control
@@ -88,6 +91,11 @@ module Fzeet
88
91
  def initialize(parent, id, opts = {}, &block)
89
92
  super('Scintilla', parent, id, opts)
90
93
 
94
+ @dirty = false
95
+
96
+ on(:savepointleft) { @dirty = true }
97
+ on(:savepointreached) { @dirty = false }
98
+
91
99
  @parent.on(:notify, @id, &block) if block
92
100
  end
93
101
 
@@ -0,0 +1,174 @@
1
+ require_relative 'Common'
2
+
3
+ module Fzeet
4
+ class WebBrowser < Windows::WebBrowser
5
+ def initialize(parent)
6
+ @parent = parent
7
+
8
+ @oips = Windows::OleInPlaceSite.new
9
+
10
+ @oips.instance_variable_set(:@browser, self)
11
+
12
+ class << @oips
13
+ attr_reader :browser
14
+
15
+ def CanInPlaceActivate
16
+ Windows::S_OK
17
+ end
18
+
19
+ def GetWindow(phwnd)
20
+ phwnd.write_pointer(browser.parent.handle)
21
+
22
+ Windows::S_OK
23
+ end
24
+
25
+ def GetWindowContext(pframe, pdoc, prPos, prClip, pinfo)
26
+ pframe.write_pointer(0)
27
+ pdoc.write_pointer(0)
28
+ Windows.GetClientRect(browser.parent.handle, prPos)
29
+ Windows.GetClientRect(browser.parent.handle, prClip)
30
+
31
+ Windows::S_OK
32
+ end
33
+
34
+ def OnPosRectChange(prPos)
35
+ browser.QueryInstance(Windows::OleInPlaceObject) { |oipo|
36
+ oipo.SetObjectRects(prPos, prPos)
37
+ }
38
+
39
+ Windows::S_OK
40
+ end
41
+ end
42
+
43
+ @ocs = Windows::OleClientSite.new
44
+
45
+ @ocs.instance_variable_set(:@browser, self)
46
+
47
+ class << @ocs
48
+ attr_reader :browser
49
+
50
+ def QueryInterface(piid, ppv)
51
+ if Windows::GUID.new(piid) == Windows::IOleInPlaceSite::IID
52
+ ppv.write_pointer(browser.oips); browser.oips.AddRef
53
+
54
+ return Windows::S_OK
55
+ end
56
+
57
+ super
58
+ end
59
+ end
60
+
61
+ super()
62
+
63
+ @events = Windows::WebBrowserEvents.new
64
+
65
+ @events.instance_variable_set(:@browser, self)
66
+
67
+ class << @events
68
+ attr_reader :browser
69
+
70
+ bstrs = []
71
+
72
+ params = Class.new(FFI::Struct) {
73
+ layout \
74
+ :array, [Windows::PARAMDATA, 1]
75
+ }.new
76
+
77
+ param1 = params[:array][0]
78
+
79
+ param1[:szName] = bstrs.push(Windows::SysAllocString("URL\0".encode('utf-16le'))).last
80
+ param1[:vt] = Windows::VT_BSTR
81
+
82
+ methods = Class.new(FFI::Struct) {
83
+ layout \
84
+ :array, [Windows::METHODDATA, 1]
85
+ }.new
86
+
87
+ method1 = methods[:array][0]
88
+
89
+ method1[:szName] = bstrs.push(Windows::SysAllocString("NavigateComplete\0".encode('utf-16le'))).last
90
+ method1[:ppdata] = params[:array]
91
+ method1[:dispid] = Windows::DISPID_NAVIGATECOMPLETE
92
+ method1[:iMeth] = 8
93
+ method1[:cc] = Windows::CC_STDCALL
94
+ method1[:cArgs] = 1
95
+ method1[:wFlags] = Windows::DISPATCH_METHOD
96
+ method1[:vtReturn] = Windows::VT_EMPTY
97
+
98
+ interface = Windows::INTERFACEDATA.new
99
+
100
+ interface[:pmethdata] = methods[:array]
101
+ interface[:cMembers] = 1
102
+
103
+ FFI::MemoryPointer.new(:pointer) { |pinfo|
104
+ Windows.DetonateHresult(:CreateDispTypeInfo, interface, Windows.GetSystemDefaultLCID, pinfo)
105
+
106
+ TypeInfo = pinfo.read_pointer
107
+ }
108
+
109
+ bstrs.each { |bstr| Windows.SysFreeString(bstr) }
110
+
111
+ def Invoke(dispid, *rest)
112
+ return Windows::E_NOTIMPL unless dispid == Windows::DISPID_NAVIGATECOMPLETE
113
+
114
+ Windows.DetonateHresult(:DispInvoke, self, TypeInfo, dispid, *rest[2..-1])
115
+
116
+ Windows::S_OK
117
+ end
118
+ end
119
+
120
+ QueryInstance(Windows::ConnectionPointContainer) { |cpc|
121
+ FFI::MemoryPointer.new(:pointer) { |pcp|
122
+ cpc.FindConnectionPoint(Windows::WebBrowserEvents::IID, pcp)
123
+
124
+ @cp = Windows::ConnectionPoint.new(pcp.read_pointer)
125
+ }
126
+ }
127
+
128
+ @cookie = nil
129
+ FFI::MemoryPointer.new(:ulong) { |p| @cp.Advise(@events, p); @cookie = p.get_ulong(0) }
130
+
131
+ QueryInstance(Windows::OleObject) { |oo|
132
+ oo.SetClientSite(@ocs)
133
+ oo.DoVerb(Windows::OLEIVERB_INPLACEACTIVATE, nil, @ocs, 0, @parent.handle, @parent.rect)
134
+ }
135
+
136
+ @parent.
137
+ on(:size) {
138
+ r = @parent.rect
139
+
140
+ put_Top(r[:top]); put_Left(r[:left]); put_Width(r[:right]); put_Height(r[:bottom])
141
+ }.
142
+
143
+ on(:destroy) {
144
+ @oips.Release
145
+ @ocs.Release
146
+ @cp.Unadvise(@cookie)
147
+ @events.Release
148
+ @cp.Release
149
+ Release()
150
+ }.
151
+
152
+ instance_variable_set(:@__WebBrowser__, self)
153
+ end
154
+
155
+ attr_reader :parent, :oips, :ocs, :events, :cp
156
+
157
+ def goto(where)
158
+ where = Windows.SysAllocString("#{where}\0".encode('utf-16le'))
159
+
160
+ Navigate(where, nil, nil, nil, nil)
161
+
162
+ self
163
+ ensure
164
+ Windows.SysFreeString(where)
165
+ end
166
+
167
+ def back; GoBack(); self; rescue; self end
168
+ def forward; GoForward(); self; rescue; self end
169
+ def home; GoHome(); self end
170
+ def search; GoSearch(); self end
171
+
172
+ def refresh; Refresh(); self end
173
+ end
174
+ end
data/lib/fzeet/Control.rb CHANGED
@@ -15,3 +15,5 @@ require_relative 'Control/TreeView'
15
15
  require_relative 'Control/ProgressBar'
16
16
  require_relative 'Control/PropertySheet'
17
17
  require_relative 'Control/Tab'
18
+ require_relative 'Control/ExplorerBrowser' if Fzeet::Windows::WINVER.AtLeastWindowsVista?
19
+ require_relative 'Control/WebBrowser'
@@ -31,7 +31,7 @@ module Fzeet
31
31
  @struct[:hInstance] = Windows.GetModuleHandle(nil)
32
32
  @struct[:lpstrFile] = @buf = FFI::MemoryPointer.new(:char, 4096)
33
33
  @struct[:nMaxFile] = @buf.size
34
- @struct[:Flags] = Fzeet.flags([:enablehook, :explorer, :enablesizing] + [*_opts[:flags]], :ofn_)
34
+ @struct[:Flags] = Fzeet.flags([:enablehook, :explorer, :enablesizing, :overwriteprompt] + [*_opts[:flags]], :ofn_)
35
35
  @struct[:lCustData] = object_id
36
36
  @struct[:lpfnHook] = HookProc
37
37
 
@@ -70,6 +70,12 @@ module Fzeet
70
70
 
71
71
  result.map! { |name| "#{path}\\#{name}" }
72
72
  end
73
+
74
+ def multiselect=(multiselect)
75
+ (multiselect) ?
76
+ @struct[:Flags] |= Windows::OFN_ALLOWMULTISELECT :
77
+ @struct[:Flags] &= ~Windows::OFN_ALLOWMULTISELECT
78
+ end
73
79
  end
74
80
 
75
81
  class FileSaveDialog < FileDialog
@@ -59,6 +59,18 @@ module Fzeet
59
59
  Release()
60
60
  end if block_given?
61
61
  end
62
+
63
+ def multiselect=(multiselect)
64
+ if multiselect
65
+ SetOptions(Windows::FOS_ALLOWMULTISELECT)
66
+ else
67
+ opts = nil
68
+
69
+ FFI::MemoryPointer.new(:pointer) { |p| GetOptions(p); opts = p.get_ulong(0) }
70
+
71
+ SetOptions(opts & ~Windows::FOS_ALLOWMULTISELECT)
72
+ end
73
+ end
62
74
  end
63
75
 
64
76
  class ShellFileSaveDialog < Windows::FileSaveDialog