fzeet 0.4.1 → 0.4.2
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.
- data/examples/Command.rbw +9 -11
- data/examples/Control/Button.rbw +19 -0
- data/examples/Dialog.rbw +43 -0
- data/examples/DialogApplication.rbw +22 -0
- data/examples/Inheritance.rbw +44 -0
- data/examples/Inheritance1.rbw +43 -0
- data/examples/LifeCycle.rbw +1 -1
- data/examples/LifeCycle2.rbw +1 -1
- data/examples/LifeCycleNC.rbw +1 -1
- data/examples/Menu/ContextMenu.rbw +15 -0
- data/examples/Menu/Menu.rbw +31 -22
- data/examples/Menu/MenuPARGB32.rbw +22 -0
- data/examples/MinimalOpts.rbw +7 -0
- data/examples/Scribble.rbw +26 -0
- data/examples/res/edit-copy.bmp +0 -0
- data/examples/res/edit-cut.bmp +0 -0
- data/examples/res/edit-paste.bmp +0 -0
- data/lib/fzeet/Accelerator.rb +1 -1
- data/lib/fzeet/Application.rb +24 -5
- data/lib/fzeet/Control.rb +32 -3
- data/lib/fzeet/Menu.rb +37 -1
- data/lib/fzeet/Window.rb +177 -18
- data/lib/fzeet/WindowMethods.rb +41 -7
- data/lib/fzeet/common.rb +214 -6
- data/lib/fzeet/windows/comctl.rb +59 -0
- data/lib/fzeet/windows/common.rb +25 -1
- data/lib/fzeet/windows/gdi.rb +3 -0
- data/lib/fzeet/windows/user.rb +252 -34
- data/lib/fzeet/windows/userctl.rb +68 -0
- data/lib/fzeet/windows/usermsg.rb +265 -0
- data/lib/fzeet/windows.rb +4 -0
- data/lib/fzeet.rb +0 -2
- metadata +19 -4
data/examples/Command.rbw
CHANGED
@@ -3,20 +3,18 @@ require 'fzeet'
|
|
3
3
|
include Fzeet
|
4
4
|
|
5
5
|
Application.run { |window|
|
6
|
-
window.
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
append(:string, "Item&1\tAlt+I", :item1)
|
11
|
-
)
|
6
|
+
window.menu = Menu.new.
|
7
|
+
append(:popup, 'Menu&1', PopupMenu.new.
|
8
|
+
append(:string, "Item&1\tAlt+I", :item1)
|
9
|
+
)
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
Application.accelerators << AcceleratorTable.new(
|
12
|
+
[:alt, :I, :item1]
|
13
|
+
)
|
16
14
|
|
17
|
-
|
18
|
-
}.
|
15
|
+
Button.new(window, :button1, x: 10, y: 10, width: 76, height: 24)
|
19
16
|
|
17
|
+
window.
|
20
18
|
on(:command, :item1) {
|
21
19
|
message 'on(:command, :item1)'
|
22
20
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'fzeet'
|
2
|
+
|
3
|
+
include Fzeet
|
4
|
+
|
5
|
+
Application.run { |window|
|
6
|
+
Button.new(window, :button1, x: 10, y: 10, width: 76, height: 24) {
|
7
|
+
message 'on(:command, :button1)'
|
8
|
+
}
|
9
|
+
|
10
|
+
Button.new(window, :button2, x: 10, y: 40, width: 76, height: 24, style: :notify,
|
11
|
+
doubleclicked: -> { message 'on(:command, :button2, :doubleclicked)' }
|
12
|
+
)
|
13
|
+
|
14
|
+
Button.new(window, :button3, x: 10, y: 70, width: 76, height: 24, style: :splitbutton)
|
15
|
+
|
16
|
+
window[:button3].on(:dropdown) {
|
17
|
+
message 'on(:notify, :button3, :dropdown)'
|
18
|
+
}
|
19
|
+
}
|
data/examples/Dialog.rbw
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'fzeet'
|
2
|
+
|
3
|
+
include Fzeet
|
4
|
+
|
5
|
+
Application.run { |window|
|
6
|
+
Button.new(window, :modeless, x: 10, y: 10, width: 76, height: 24) {
|
7
|
+
Dialog.new(window, caption: 'Modeless', x: 100, y: 100) { |args|
|
8
|
+
dialog = args[:window]
|
9
|
+
|
10
|
+
Button.new(dialog, :ok, x: 228, y: 242, width: 76, height: 24) {
|
11
|
+
dialog.dispose; window[:modeless].toggle(:enabled)
|
12
|
+
}
|
13
|
+
|
14
|
+
Button.new(dialog, :cancel, x: 308, y: 242, width: 76, height: 24) {
|
15
|
+
dialog.dispose; window[:modeless].toggle(:enabled)
|
16
|
+
}
|
17
|
+
|
18
|
+
Button.new(dialog, :button1, x: 10, y: 10, width: 76, height: 24) {
|
19
|
+
dialog.message 'clicked'
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
window[:modeless].toggle(:enabled)
|
24
|
+
}
|
25
|
+
|
26
|
+
Button.new(window, :modal, x: 90, y: 10, width: 76, height: 24) {
|
27
|
+
message(Dialog.new(window, modal: true, caption: 'Modal', x: 150, y: 150) { |args|
|
28
|
+
dialog = args[:window]
|
29
|
+
|
30
|
+
Button.new(dialog, :ok, x: 228, y: 242, width: 76, height: 24) {
|
31
|
+
dialog.end(:ok)
|
32
|
+
}
|
33
|
+
|
34
|
+
Button.new(dialog, :cancel, x: 308, y: 242, width: 76, height: 24) {
|
35
|
+
dialog.end(:cancel)
|
36
|
+
}
|
37
|
+
|
38
|
+
Button.new(dialog, :button1, x: 10, y: 10, width: 76, height: 24) {
|
39
|
+
dialog.message 'clicked'
|
40
|
+
}
|
41
|
+
}.result.ok?)
|
42
|
+
}
|
43
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'fzeet'
|
2
|
+
|
3
|
+
include Fzeet
|
4
|
+
|
5
|
+
Dialog.new(nil, modal: true, style: [:overlappedwindow, :center]) { |args|
|
6
|
+
dialog = Application.window = args[:window]
|
7
|
+
|
8
|
+
dialog.menu = Menu.new.
|
9
|
+
append(:popup, 'Menu&1', PopupMenu.new.
|
10
|
+
append(:string, 'Item&1', :item1).
|
11
|
+
append(:separator).
|
12
|
+
append(:string, 'E&xit', :exit)
|
13
|
+
)
|
14
|
+
|
15
|
+
Button.new(dialog, :button1, caption: '&Button1', x: 10, y: 10, width: 76, height: 24)
|
16
|
+
|
17
|
+
dialog.
|
18
|
+
on(:command, :exit) { dialog.end(:ok) }.
|
19
|
+
on(:command, :cancel) { dialog.end(:cancel) if question('Close?').yes? }.
|
20
|
+
on(:command, :item1) { message 'on(:command, :item1)' }.
|
21
|
+
on(:command, :button1) { message 'on(:command, :button1)' }
|
22
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'fzeet'
|
2
|
+
|
3
|
+
include Fzeet
|
4
|
+
|
5
|
+
class Window1 < Window
|
6
|
+
message <<-MSG
|
7
|
+
class: #{self}
|
8
|
+
superclass: #{self.superclass}
|
9
|
+
WindowClass: #{self::WindowClass.name}
|
10
|
+
WindowClass.prototype: #{self::WindowClass.prototype.name}
|
11
|
+
MSG
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
super
|
15
|
+
|
16
|
+
self.menu = Menu.new.
|
17
|
+
append(:popup, 'Menu&1', PopupMenu.new.
|
18
|
+
append(:string, 'Item&1', :item1)
|
19
|
+
)
|
20
|
+
|
21
|
+
on(:command, :item1, &method(:onItem1))
|
22
|
+
end
|
23
|
+
|
24
|
+
def onItem1(args)
|
25
|
+
message "Window1##{__method__}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Window2 < Window1
|
30
|
+
message <<-MSG
|
31
|
+
class: #{self}
|
32
|
+
superclass: #{self.superclass}
|
33
|
+
WindowClass: #{self::WindowClass.name}
|
34
|
+
WindowClass.prototype: #{self::WindowClass.prototype.name}
|
35
|
+
MSG
|
36
|
+
|
37
|
+
def onItem1(args)
|
38
|
+
message "Window2##{__method__}"
|
39
|
+
|
40
|
+
super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Application.run(Window2.new)
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'fzeet'
|
2
|
+
|
3
|
+
include Fzeet
|
4
|
+
|
5
|
+
Window1 = Window['X.Window1',
|
6
|
+
background: SystemBrush.new(:appworkspace)
|
7
|
+
]
|
8
|
+
|
9
|
+
class Window1
|
10
|
+
message <<-MSG
|
11
|
+
class: #{self}
|
12
|
+
superclass: #{self.superclass}
|
13
|
+
WindowClass: #{self::WindowClass.name}
|
14
|
+
WindowClass.prototype: #{self::WindowClass.prototype.name}
|
15
|
+
MSG
|
16
|
+
|
17
|
+
def initialize(opts = {})
|
18
|
+
(opts[:style] ||= []) << :hscroll
|
19
|
+
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
Window2 = Window1['X.Window2',
|
25
|
+
cursor: SystemCursor.new(:hand)
|
26
|
+
]
|
27
|
+
|
28
|
+
class Window2
|
29
|
+
message <<-MSG
|
30
|
+
class: #{self}
|
31
|
+
superclass: #{self.superclass}
|
32
|
+
WindowClass: #{self::WindowClass.name}
|
33
|
+
WindowClass.prototype: #{self::WindowClass.prototype.name}
|
34
|
+
MSG
|
35
|
+
|
36
|
+
def initialize(opts = {})
|
37
|
+
(opts[:style] ||= []) << :vscroll
|
38
|
+
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Application.run(Window2.new)
|
data/examples/LifeCycle.rbw
CHANGED
data/examples/LifeCycle2.rbw
CHANGED
data/examples/LifeCycleNC.rbw
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'fzeet'
|
2
|
+
|
3
|
+
include Fzeet
|
4
|
+
|
5
|
+
Application.run { |window|
|
6
|
+
window.
|
7
|
+
on(:contextmenu) { |args| using(
|
8
|
+
PopupMenu.new.
|
9
|
+
append(:string, 'Item&1', :item1)
|
10
|
+
) { |popup|
|
11
|
+
popup.track(window, args[:x], args[:y])
|
12
|
+
}}.
|
13
|
+
|
14
|
+
on(:command, :item1) { message 'on(:command, :item1)' }
|
15
|
+
}
|
data/examples/Menu/Menu.rbw
CHANGED
@@ -3,33 +3,30 @@ require 'fzeet'
|
|
3
3
|
include Fzeet
|
4
4
|
|
5
5
|
Application.run { |window|
|
6
|
-
window.
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
append([:string, :grayed], 'Item&2', :item2).
|
12
|
-
append([:string, :checked], 'Item&3', :item3).
|
6
|
+
window.menu = Menu.new.
|
7
|
+
append(:popup, 'Menu&1', PopupMenu.new.
|
8
|
+
append(:string, 'Item&1', :item1).
|
9
|
+
append([:string, :grayed], 'Item&2', :item2).
|
10
|
+
append([:string, :checked], 'Item&3', :item3).
|
13
11
|
|
14
|
-
|
12
|
+
append(:separator).
|
15
13
|
|
16
|
-
|
17
|
-
|
14
|
+
append([:string, :radiocheck, :checked], 'Item&4', :item4).
|
15
|
+
append([:string, :radiocheck], 'Item&5', :item5).
|
18
16
|
|
19
|
-
|
17
|
+
append(:separator).
|
20
18
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
append(:popup, 'Menu&2', PopupMenu.new.
|
20
|
+
append([:string, :radiocheck, :checked], 'Item&6', :item6).
|
21
|
+
append([:string, :radiocheck], 'Item&7', :item7)
|
22
|
+
)
|
23
|
+
).
|
26
24
|
|
27
|
-
|
25
|
+
append(:string, 'Item&8', :item8).
|
28
26
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
}
|
27
|
+
append([:popup, :rightjustify], 'Menu&3', PopupMenu.new.
|
28
|
+
append(:string, 'Item&9', :item9)
|
29
|
+
)
|
33
30
|
|
34
31
|
window.
|
35
32
|
on(:command, :item1) { window.menu[:item2].toggle(:enabled) }.
|
@@ -44,5 +41,17 @@ Application.run { |window|
|
|
44
41
|
window.on(:command, id) { window.menu[id].select(:item6, :item7) }
|
45
42
|
}
|
46
43
|
|
47
|
-
window.
|
44
|
+
window.
|
45
|
+
on(:command, :item8) { message 'on(:command, :item8)' }.
|
46
|
+
|
47
|
+
on(:command, :item9) {
|
48
|
+
message <<-MSG
|
49
|
+
window.menu[:item2].enabled? - #{window.menu[:item2].enabled?}
|
50
|
+
window.menu[:item3].checked? - #{window.menu[:item3].checked?}
|
51
|
+
window.menu[:item4].checked? - #{window.menu[:item4].checked?}
|
52
|
+
window.menu[:item5].checked? - #{window.menu[:item5].checked?}
|
53
|
+
window.menu[:item6].checked? - #{window.menu[:item6].checked?}
|
54
|
+
window.menu[:item7].checked? - #{window.menu[:item7].checked?}
|
55
|
+
MSG
|
56
|
+
}
|
48
57
|
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'fzeet'
|
2
|
+
|
3
|
+
include Fzeet
|
4
|
+
|
5
|
+
Application.run { |window|
|
6
|
+
images = {
|
7
|
+
cut: PARGB32.new('../res/edit-cut.bmp'),
|
8
|
+
copy: PARGB32.new('../res/edit-copy.bmp'),
|
9
|
+
paste: PARGB32.new('../res/edit-paste.bmp')
|
10
|
+
}
|
11
|
+
|
12
|
+
window.menu = Menu.new.
|
13
|
+
append(:popup, '&Edit', PopupMenu.new.
|
14
|
+
append(:string, 'Cu&t', :cut).
|
15
|
+
append(:string, '&Copy', :copy).
|
16
|
+
append(:string, '&Paste', :paste)
|
17
|
+
)
|
18
|
+
|
19
|
+
window.menu.images = images
|
20
|
+
|
21
|
+
window.on(:destroy) { images.values.each(&:dispose) }
|
22
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'fzeet'
|
2
|
+
|
3
|
+
include Fzeet
|
4
|
+
|
5
|
+
Application.run { |window|
|
6
|
+
dc = nil
|
7
|
+
|
8
|
+
window.
|
9
|
+
on(:lbuttondown) { |args|
|
10
|
+
window.capture = true
|
11
|
+
dc = ClientDC.new(window)
|
12
|
+
|
13
|
+
dc.move(args[:x], args[:y])
|
14
|
+
}.
|
15
|
+
|
16
|
+
on(:lbuttonup) {
|
17
|
+
dc.dispose; dc = nil
|
18
|
+
window.capture = false
|
19
|
+
}.
|
20
|
+
|
21
|
+
on(:mousemove) { |args|
|
22
|
+
next unless window.capture?
|
23
|
+
|
24
|
+
dc.line(args[:x], args[:y])
|
25
|
+
}
|
26
|
+
}
|
Binary file
|
Binary file
|
Binary file
|
data/lib/fzeet/Accelerator.rb
CHANGED
@@ -13,7 +13,7 @@ module Fzeet
|
|
13
13
|
args.each_with_index { |data, i|
|
14
14
|
accel = Windows::ACCEL.new(paccels + i * Windows::ACCEL.size)
|
15
15
|
|
16
|
-
accel[:fVirt] =
|
16
|
+
accel[:fVirt] = Fzeet.flags(data[0], :f)
|
17
17
|
accel[:fVirt] |= Windows::FVIRTKEY if data[1].kind_of?(Symbol)
|
18
18
|
accel[:key] = data[1].to_s.ord
|
19
19
|
accel[:cmd] = Command[data[2]]
|
data/lib/fzeet/Application.rb
CHANGED
@@ -2,7 +2,7 @@ require_relative 'common'
|
|
2
2
|
|
3
3
|
module Fzeet
|
4
4
|
class Application
|
5
|
-
@name = File.basename($0, '
|
5
|
+
@name = File.basename($0, '.rbw')
|
6
6
|
@version = '0.1.0'
|
7
7
|
@authors = []
|
8
8
|
|
@@ -10,14 +10,32 @@ module Fzeet
|
|
10
10
|
|
11
11
|
@window = nil
|
12
12
|
@accelerators = []
|
13
|
+
@dialogs = []
|
13
14
|
|
14
15
|
class << self
|
15
16
|
attr_accessor :name, :version, :authors, :quitWhenMainWindowCloses
|
16
|
-
attr_reader :window, :accelerators
|
17
|
+
attr_reader :window, :accelerators, :dialogs
|
17
18
|
end
|
18
19
|
|
19
|
-
def self.
|
20
|
-
|
20
|
+
def self.window=(window)
|
21
|
+
raise 'Application.window already set.' if @window
|
22
|
+
|
23
|
+
@window = window
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.run(windowOrOpts = {}, &block)
|
27
|
+
@window = case windowOrOpts
|
28
|
+
when Window; windowOrOpts.tap { |window| block.call(window) if block }
|
29
|
+
when Hash
|
30
|
+
if windowOrOpts[:deferCreateWindow].tap { windowOrOpts.delete_if { |k, v| k == :deferCreateWindow } }
|
31
|
+
Window.new(windowOrOpts, &block)
|
32
|
+
else
|
33
|
+
Window.new(windowOrOpts).tap { |window| block.call(window) if block }
|
34
|
+
end
|
35
|
+
else raise ArgumentError
|
36
|
+
end
|
37
|
+
|
38
|
+
return 0 if window.handle.null?
|
21
39
|
|
22
40
|
@window.on(:destroy) { quit } if @quitWhenMainWindowCloses
|
23
41
|
|
@@ -27,7 +45,8 @@ module Fzeet
|
|
27
45
|
|
28
46
|
while msg.get!
|
29
47
|
msg.translate.dispatch unless
|
30
|
-
accelerators.any? { |table| table.translate?(msg, @window) }
|
48
|
+
accelerators.any? { |table| table.translate?(msg, @window) } ||
|
49
|
+
dialogs.any? { |dialog| dialog.dlgmsg?(msg) }
|
31
50
|
end
|
32
51
|
|
33
52
|
msg[:wParam]
|
data/lib/fzeet/Control.rb
CHANGED
@@ -14,14 +14,24 @@ module Fzeet
|
|
14
14
|
at_exit { Font.dispose }
|
15
15
|
}
|
16
16
|
|
17
|
+
def self.crackNotification(args) end
|
18
|
+
|
17
19
|
def initialize(className, parent, id, opts = {})
|
18
20
|
@parent = parent
|
19
21
|
@id = Command[id]
|
20
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
|
+
|
21
31
|
_opts = {
|
22
32
|
xstyle: [],
|
23
33
|
caption: id.capitalize,
|
24
|
-
style: [
|
34
|
+
style: [],
|
25
35
|
x: Windows::CW_USEDEFAULT,
|
26
36
|
y: Windows::CW_USEDEFAULT,
|
27
37
|
width: Windows::CW_USEDEFAULT,
|
@@ -30,9 +40,9 @@ module Fzeet
|
|
30
40
|
badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
|
31
41
|
_opts.merge!(opts)
|
32
42
|
|
33
|
-
_opts[:xstyle] = _opts[:xstyle]
|
43
|
+
_opts[:xstyle] = Fzeet.flags(_opts[:xstyle], *self.class::Prefix[:xstyle])
|
34
44
|
_opts[:caption] = _opts[:caption].to_s
|
35
|
-
_opts[:style] =
|
45
|
+
_opts[:style] = Fzeet.flags([:child, :visible, :tabstop], :ws_) | Fzeet.flags(_opts[:style], *self.class::Prefix[:style])
|
36
46
|
|
37
47
|
@handle = Windows.DetonateLastError(FFI::Pointer::NULL, :CreateWindowEx,
|
38
48
|
_opts[:xstyle], className, _opts[:caption], _opts[:style],
|
@@ -43,6 +53,8 @@ module Fzeet
|
|
43
53
|
attach
|
44
54
|
|
45
55
|
sendmsg(:setfont, Font.handle, 1)
|
56
|
+
|
57
|
+
handlers.each { |k, v| on(k, &v) }
|
46
58
|
end
|
47
59
|
|
48
60
|
attr_reader :parent, :id
|
@@ -51,10 +63,27 @@ module Fzeet
|
|
51
63
|
end
|
52
64
|
|
53
65
|
class Button < Control
|
66
|
+
Prefix = {
|
67
|
+
xstyle: [:ws_ex_],
|
68
|
+
style: [:bs_, :ws_],
|
69
|
+
message: [:bm_, :bcm_, :ccm_, :wm_],
|
70
|
+
notification: [:bn_, :bcn_, :nm_]
|
71
|
+
}
|
72
|
+
|
54
73
|
def initialize(parent, id, opts = {}, &block)
|
55
74
|
super('Button', parent, id, opts)
|
56
75
|
|
57
76
|
@parent.on(:command, @id, &block) if block
|
58
77
|
end
|
78
|
+
|
79
|
+
def on(notification, &block)
|
80
|
+
if (notification = Fzeet.constant(notification, *self.class::Prefix[:notification])) < Windows::BCN_LAST
|
81
|
+
@parent.on(:command, @id, notification, &block)
|
82
|
+
else
|
83
|
+
@parent.on(:notify, @id, notification, &block)
|
84
|
+
end
|
85
|
+
|
86
|
+
self
|
87
|
+
end
|
59
88
|
end
|
60
89
|
end
|
data/lib/fzeet/Menu.rb
CHANGED
@@ -43,6 +43,38 @@ module Fzeet
|
|
43
43
|
|
44
44
|
self
|
45
45
|
end
|
46
|
+
|
47
|
+
def info(mask)
|
48
|
+
Windows.DetonateLastError(0, :GetMenuItemInfo,
|
49
|
+
@menu.handle,
|
50
|
+
@id,
|
51
|
+
0,
|
52
|
+
info = Windows::MENUITEMINFO.new.tap { |mii|
|
53
|
+
mii[:cbSize] = mii.size
|
54
|
+
mii[:fMask] = Fzeet.constant(mask, :miim_)
|
55
|
+
}
|
56
|
+
)
|
57
|
+
|
58
|
+
info
|
59
|
+
end
|
60
|
+
|
61
|
+
def info=(mii)
|
62
|
+
Windows.DetonateLastError(0, :SetMenuItemInfo,
|
63
|
+
@menu.handle,
|
64
|
+
@id,
|
65
|
+
0,
|
66
|
+
mii.tap { mii[:cbSize] = mii.size }
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
def image; (Handle.instance?(handle = info(:bitmap)[:hbmpItem])) ? Handle.instance(handle) : nil end
|
71
|
+
|
72
|
+
def image=(image)
|
73
|
+
self.info = Windows::MENUITEMINFO.new.tap { |mii|
|
74
|
+
mii[:fMask] = Windows::MIIM_BITMAP
|
75
|
+
mii[:hbmpItem] = image.handle
|
76
|
+
}
|
77
|
+
end
|
46
78
|
end
|
47
79
|
|
48
80
|
module MenuMethods
|
@@ -53,7 +85,7 @@ module Fzeet
|
|
53
85
|
def append(flags, item = nil, id = 0)
|
54
86
|
Windows.DetonateLastError(0, :AppendMenu,
|
55
87
|
@handle,
|
56
|
-
|
88
|
+
Fzeet.flags(flags, :mf_, :mft_, :mfs_),
|
57
89
|
case id
|
58
90
|
when Integer; id
|
59
91
|
when Symbol; Command[id]
|
@@ -65,6 +97,8 @@ module Fzeet
|
|
65
97
|
|
66
98
|
self
|
67
99
|
end
|
100
|
+
|
101
|
+
def images=(images) images.each { |id, image| self[id].image = image } end
|
68
102
|
end
|
69
103
|
|
70
104
|
class Menu < Handle
|
@@ -93,5 +127,7 @@ module Fzeet
|
|
93
127
|
attr_reader :submenus
|
94
128
|
|
95
129
|
def dispose; Windows.DestroyMenu(@handle); rdetach end
|
130
|
+
|
131
|
+
def track(window, x, y, flags = 0) Windows.TrackPopupMenu(@handle, Fzeet.flags(flags, :tpm_), x, y, 0, window.handle, nil); self end
|
96
132
|
end
|
97
133
|
end
|