fzeet 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/examples/Command.rbw CHANGED
@@ -2,4 +2,32 @@ require 'fzeet'
2
2
 
3
3
  include Fzeet
4
4
 
5
- message 'TODO...'
5
+ Application.run { |window|
6
+ window.
7
+ on(:create) {
8
+ window.menu = Menu.new.
9
+ append(:popup, 'Menu&1', PopupMenu.new.
10
+ append(:string, "Item&1\tAlt+I", :item1)
11
+ )
12
+
13
+ Application.accelerators << AcceleratorTable.new(
14
+ [:alt, :I, :item1]
15
+ )
16
+
17
+ Button.new(window, :button1, x: 10, y: 10, width: 76, height: 24)
18
+ }.
19
+
20
+ on(:command, :item1) {
21
+ message 'on(:command, :item1)'
22
+
23
+ window[:button1].enabled = true
24
+ window.menu[:item1].enabled = false
25
+ }.
26
+
27
+ on(:command, :button1) { |args|
28
+ message 'on(:command, :button1)'
29
+
30
+ window.menu[:item1].enabled = true
31
+ args[:sender].enabled = false
32
+ }
33
+ }
@@ -15,11 +15,11 @@ class LifeCycle1Window < Window
15
15
  args[:result] = -1 if question('Create?').no?
16
16
  end
17
17
 
18
- def onClose(args)
18
+ def onClose
19
19
  dispose if question('Close?', buttons: [:yes, :No]).yes?
20
20
  end
21
21
 
22
- def onDestroy(args)
22
+ def onDestroy
23
23
  message __method__
24
24
  end
25
25
  end
@@ -0,0 +1,30 @@
1
+ require 'fzeet'
2
+
3
+ include Fzeet
4
+
5
+ Application.quitWhenMainWindowCloses = false
6
+
7
+ Application.run { |window|
8
+ window.
9
+ on(:nccreate) { |args|
10
+ args[:result] = 0 if question('NCCreate?').no?
11
+ }.
12
+
13
+ on(:create) { |args|
14
+ args[:result] = -1 if question('Create?').no?
15
+ }.
16
+
17
+ on(:close) {
18
+ window.dispose if question('Close?', buttons: [:yes, :No]).yes?
19
+ }.
20
+
21
+ on(:destroy) {
22
+ message 'on(:destroy)'
23
+ }.
24
+
25
+ on(:ncdestroy) {
26
+ message 'on(:ncdestroy)'
27
+
28
+ Application.quit
29
+ }
30
+ }
@@ -0,0 +1,48 @@
1
+ require 'fzeet'
2
+
3
+ include Fzeet
4
+
5
+ Application.run { |window|
6
+ window.
7
+ on(:create) {
8
+ window.menu = Menu.new.
9
+ append(:popup, 'Menu&1', PopupMenu.new.
10
+ append(:string, 'Item&1', :item1).
11
+ append([:string, :grayed], 'Item&2', :item2).
12
+ append([:string, :checked], 'Item&3', :item3).
13
+
14
+ append(:separator).
15
+
16
+ append([:string, :usecheckbitmaps, :checked], 'Item&4', :item4).
17
+ append([:string, :usecheckbitmaps], 'Item&5', :item5).
18
+
19
+ append(:separator).
20
+
21
+ append(:popup, 'Menu&2', PopupMenu.new.
22
+ append([:string, :usecheckbitmaps, :checked], 'Item&6', :item6).
23
+ append([:string, :usecheckbitmaps], 'Item&7', :item7)
24
+ )
25
+ ).
26
+
27
+ append(:string, 'Item&8', :item8).
28
+
29
+ append([:popup, :rightjustify], 'Menu&3', PopupMenu.new.
30
+ append(:string, 'Item&9', :item9)
31
+ )
32
+ }
33
+
34
+ window.
35
+ on(:command, :item1) { window.menu[:item2].toggle(:enabled) }.
36
+ on(:command, :item2) { message 'on(:command, :item2)' }.
37
+ on(:command, :item3) { window.menu[:item3].toggle(:checked) }
38
+
39
+ [:item4, :item5].each { |id|
40
+ window.on(:command, id) { window.menu[id].select(:item4, :item5) }
41
+ }
42
+
43
+ [:item6, :item7].each { |id|
44
+ window.on(:command, id) { window.menu[id].select(:item6, :item7) }
45
+ }
46
+
47
+ window.on(:command, :item8) { message 'on(:command, :item8)' }
48
+ }
data/examples/Minimal.rbw CHANGED
@@ -2,4 +2,6 @@ require 'fzeet'
2
2
 
3
3
  include Fzeet
4
4
 
5
- Application.run
5
+ Application.run { |window|
6
+
7
+ }
@@ -75,7 +75,7 @@ WindowProc = FFI::Function.new(:long, [:pointer, :uint, :uint, :long], conventio
75
75
  end
76
76
  end
77
77
 
78
- (result.nil?) ? DefWindowProc(hwnd, uMsg, wParam, lParam) : result
78
+ result || DefWindowProc(hwnd, uMsg, wParam, lParam)
79
79
  }
80
80
 
81
81
  wc = WNDCLASSEX.new
@@ -38,7 +38,7 @@ WindowProc = FFI::Function.new(:long, [:pointer, :uint, :uint, :long], conventio
38
38
  onDestroy(hwnd)
39
39
  end
40
40
 
41
- (result.nil?) ? DefWindowProc(hwnd, uMsg, wParam, lParam) : result
41
+ result || DefWindowProc(hwnd, uMsg, wParam, lParam)
42
42
  }
43
43
 
44
44
  wc = WNDCLASSEX.new
@@ -16,7 +16,7 @@ WindowProc = FFI::Function.new(:long, [:pointer, :uint, :uint, :long], conventio
16
16
  onDestroy(hwnd)
17
17
  end
18
18
 
19
- (result.nil?) ? DefWindowProc(hwnd, uMsg, wParam, lParam) : result
19
+ result || DefWindowProc(hwnd, uMsg, wParam, lParam)
20
20
  }
21
21
 
22
22
  wc = WNDCLASSEX.new
@@ -1,7 +1,28 @@
1
1
  require_relative 'common'
2
2
 
3
3
  module Fzeet
4
+ module AcceleratorTableMethods
5
+ def translate?(msg, window) Windows.TranslateAccelerator(window.handle, @handle, msg) != 0 end
6
+ end
7
+
4
8
  class AcceleratorTable < Handle
9
+ include AcceleratorTableMethods
10
+
11
+ def initialize(*args)
12
+ FFI::MemoryPointer.new(Windows::ACCEL, args.size) { |paccels|
13
+ args.each_with_index { |data, i|
14
+ accel = Windows::ACCEL.new(paccels + i * Windows::ACCEL.size)
15
+
16
+ accel[:fVirt] = [*data[0]].inject(0) { |flags, flag| flags |= Windows.const_get("F#{flag.upcase}") }
17
+ accel[:fVirt] |= Windows::FVIRTKEY if data[1].kind_of?(Symbol)
18
+ accel[:key] = data[1].to_s.ord
19
+ accel[:cmd] = Command[data[2]]
20
+ }
21
+
22
+ @handle = Windows.DetonateLastError(FFI::Pointer::NULL, :CreateAcceleratorTable, paccels, args.size); attach
23
+ }
24
+ end
5
25
 
26
+ def dispose; Windows.DestroyAcceleratorTable(@handle); detach end
6
27
  end
7
28
  end
@@ -6,33 +6,39 @@ module Fzeet
6
6
  @version = '0.1.0'
7
7
  @authors = []
8
8
 
9
+ @quitWhenMainWindowCloses = true
10
+
9
11
  @window = nil
12
+ @accelerators = []
10
13
 
11
14
  class << self
12
- attr_accessor :name, :version, :authors
13
- attr_reader :window
15
+ attr_accessor :name, :version, :authors, :quitWhenMainWindowCloses
16
+ attr_reader :window, :accelerators
14
17
  end
15
18
 
16
19
  def self.run(window = nil, &block)
17
20
  return 0 if (@window = window || Window.new(&block)).handle.null?
18
21
 
19
- @window.on(:destroy) { Windows.PostQuitMessage(0) }
20
-
21
- Windows.ShowWindow(@window.handle, Windows::SW_SHOWNORMAL)
22
- Windows.UpdateWindow(@window.handle)
22
+ @window.on(:destroy) { quit } if @quitWhenMainWindowCloses
23
23
 
24
- msg = Windows::MSG.new
24
+ @window.show.update
25
25
 
26
- while (get = Windows.GetMessage(msg, nil, 0, 0)) != 0
27
- raise 'GetMessage failed.' if get == -1
26
+ msg = Message.new
28
27
 
29
- Windows.TranslateMessage(msg)
30
- Windows.DispatchMessage(msg)
28
+ while msg.get!
29
+ msg.translate.dispatch unless
30
+ accelerators.any? { |table| table.translate?(msg, @window) }
31
31
  end
32
32
 
33
33
  msg[:wParam]
34
34
  rescue
35
35
  Fzeet.message %Q{#{$!}\n\n#{$!.backtrace.join("\n")}}, icon: :error
36
36
  end
37
+
38
+ def self.quit(code = 0)
39
+ accelerators.each(&:dispose)
40
+
41
+ Windows.PostQuitMessage(code)
42
+ end
37
43
  end
38
44
  end
data/lib/fzeet/Control.rb CHANGED
@@ -1,7 +1,60 @@
1
- require_relative 'common'
1
+ require_relative 'WindowMethods'
2
2
 
3
3
  module Fzeet
4
4
  class Control < Handle
5
+ include WindowMethods
5
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 initialize(className, parent, id, opts = {})
18
+ @parent = parent
19
+ @id = Command[id]
20
+
21
+ _opts = {
22
+ xstyle: [],
23
+ caption: id.capitalize,
24
+ style: [:child, :visible],
25
+ x: Windows::CW_USEDEFAULT,
26
+ y: Windows::CW_USEDEFAULT,
27
+ width: Windows::CW_USEDEFAULT,
28
+ height: Windows::CW_USEDEFAULT,
29
+ }
30
+ badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
31
+ _opts.merge!(opts)
32
+
33
+ _opts[:xstyle] = _opts[:xstyle].inject(0) { |flags, xstyle| flags |= Windows.const_get("WS_EX_#{xstyle.upcase}") }
34
+ _opts[:caption] = _opts[:caption].to_s
35
+ _opts[:style] = _opts[:style].inject(0) { |flags, style| flags |= Windows.const_get("WS_#{style.upcase}") }
36
+
37
+ @handle = Windows.DetonateLastError(FFI::Pointer::NULL, :CreateWindowEx,
38
+ _opts[:xstyle], className, _opts[:caption], _opts[:style],
39
+ _opts[:x], _opts[:y], _opts[:width], _opts[:height],
40
+ @parent.handle, FFI::Pointer.new(@id), Windows.GetModuleHandle(nil), nil
41
+ )
42
+
43
+ attach
44
+
45
+ sendmsg(:setfont, Font.handle, 1)
46
+ end
47
+
48
+ attr_reader :parent, :id
49
+
50
+ def dispose; detach end
51
+ end
52
+
53
+ class Button < Control
54
+ def initialize(parent, id, opts = {}, &block)
55
+ super('Button', parent, id, opts)
56
+
57
+ @parent.on(:command, @id, &block) if block
58
+ end
6
59
  end
7
60
  end
data/lib/fzeet/Menu.rb CHANGED
@@ -2,14 +2,96 @@ require_relative 'common'
2
2
 
3
3
  module Fzeet
4
4
  class MenuItem
5
+ include Toggle
5
6
 
7
+ def initialize(menu, id) @menu, @id = menu, Command[id] end
8
+
9
+ attr_reader :menu, :id
10
+
11
+ def enabled?
12
+ flags = Windows.DetonateLastError(-1, :GetMenuState, @menu.handle, @id, 0)
13
+
14
+ (flags & Windows::MF_GRAYED) != Windows::MF_GRAYED
15
+ end
16
+
17
+ def enabled=(enabled)
18
+ Windows.DetonateLastError(-1, :EnableMenuItem,
19
+ @menu.handle,
20
+ @id,
21
+ (enabled) ? Windows::MF_ENABLED : Windows::MF_GRAYED
22
+ )
23
+ end
24
+
25
+ def checked?
26
+ flags = Windows.DetonateLastError(-1, :GetMenuState, @menu.handle, @id, 0)
27
+
28
+ (flags & Windows::MF_CHECKED) == Windows::MF_CHECKED
29
+ end
30
+
31
+ def checked=(checked)
32
+ Windows.DetonateLastError(-1, :CheckMenuItem,
33
+ @menu.handle,
34
+ @id,
35
+ (checked) ? Windows::MF_CHECKED : Windows::MF_UNCHECKED
36
+ )
37
+ end
38
+
39
+ def select(first, last)
40
+ Windows.DetonateLastError(0, :CheckMenuRadioItem,
41
+ @menu.handle, Command[first], Command[last], @id, 0
42
+ )
43
+
44
+ self
45
+ end
46
+ end
47
+
48
+ module MenuMethods
49
+ def rdetach; submenus.each(&:rdetach); detach end
50
+
51
+ def [](id) MenuItem.new(self, id) end
52
+
53
+ def append(flags, item = nil, id = 0)
54
+ Windows.DetonateLastError(0, :AppendMenu,
55
+ @handle,
56
+ [*flags].inject(0) { |flags, flag| flags |= Windows.const_get("MF_#{flag.upcase}") },
57
+ case id
58
+ when Integer; id
59
+ when Symbol; Command[id]
60
+ when MenuMethods; submenus << id; id.handle.to_i
61
+ else raise ArgumentError
62
+ end,
63
+ item
64
+ )
65
+
66
+ self
67
+ end
6
68
  end
7
69
 
8
70
  class Menu < Handle
71
+ include MenuMethods
72
+
73
+ def initialize
74
+ @submenus = []
9
75
 
76
+ @handle = Windows.DetonateLastError(FFI::Pointer::NULL, :CreateMenu); attach
77
+ end
78
+
79
+ attr_reader :submenus
80
+
81
+ def dispose; Windows.DestroyMenu(@handle); rdetach end
10
82
  end
11
83
 
12
84
  class PopupMenu < Handle
85
+ include MenuMethods
86
+
87
+ def initialize
88
+ @submenus = []
89
+
90
+ @handle = Windows.DetonateLastError(FFI::Pointer::NULL, :CreatePopupMenu); attach
91
+ end
92
+
93
+ attr_reader :submenus
13
94
 
95
+ def dispose; Windows.DestroyMenu(@handle); rdetach end
14
96
  end
15
97
  end
data/lib/fzeet/Window.rb CHANGED
@@ -1,7 +1,9 @@
1
- require_relative 'common'
1
+ require_relative 'WindowMethods'
2
2
 
3
3
  module Fzeet
4
4
  class Window < Handle
5
+ include WindowMethods
6
+
5
7
  WindowProc = FFI::Function.new(:long, [:pointer, :uint, :uint, :long], convention: :stdcall) { |hwnd, uMsg, wParam, lParam|
6
8
  begin
7
9
  if uMsg == Windows::WM_NCCREATE
@@ -55,6 +57,9 @@ module Fzeet
55
57
  when Windows::WM_NCCREATE
56
58
  args[:result] = 1
57
59
  args[:cs] = Windows::CREATESTRUCT.new(FFI::Pointer.new(lParam))
60
+ when Windows::WM_COMMAND
61
+ args[:command], args[:notification], args[:hctl] = Windows.LOWORD(wParam), Windows.HIWORD(wParam), FFI::Pointer.new(lParam)
62
+ args[:sender] = @@instances[args[:hctl].to_i] unless args[:hctl].null?
58
63
  end
59
64
 
60
65
  args
@@ -82,6 +87,7 @@ module Fzeet
82
87
  _opts[:style] = _opts[:style].inject(0) { |flags, style| flags |= Windows.const_get("WS_#{style.upcase}") }
83
88
 
84
89
  @messages ||= {}
90
+ @commands ||= {}
85
91
 
86
92
  @processed = [0, 0]
87
93
 
@@ -92,13 +98,19 @@ module Fzeet
92
98
  )
93
99
 
94
100
  if @handle.null?
95
- raise 'CreateWindowEx failed.' unless [
101
+ raise "CreateWindowEx failed (last error #{Windows.GetLastError()})." unless [
96
102
  [Windows::WM_NCCREATE, 0], [Windows::WM_CREATE, -1],
97
103
  [Windows::WM_DESTROY, 0], [Windows::WM_NCDESTROY, 0]
98
104
  ].include?(@processed)
99
105
  else
100
106
  @parent = _opts[:parent]
101
107
  self.menu = _opts[:menu] if _opts[:menu]
108
+
109
+ on(:destroy) {
110
+ menu.rdetach if self.menu
111
+
112
+ eachChild(&:dispose)
113
+ }
102
114
  end
103
115
  end
104
116
 
@@ -113,12 +125,28 @@ module Fzeet
113
125
  args ||= self.class.crackMessage(hwnd, uMsg, wParam, lParam)
114
126
 
115
127
  handlers.each { |handler|
116
- handler.call(args)
128
+ (handler.arity == 0) ? handler.call : handler.call(args)
117
129
 
118
130
  result = args[:result]; @processed[0], @processed[1] = uMsg, result
119
131
  }
120
132
  end
121
133
 
134
+ if uMsg == Windows::WM_COMMAND && (handlers = @commands[Windows.LOWORD(wParam)])
135
+ args ||= self.class.crackMessage(hwnd, uMsg, wParam, lParam)
136
+
137
+ handlers[:all].each { |handler|
138
+ (handler.arity == 0) ? handler.call : handler.call(args)
139
+
140
+ result = args[:result]; @processed[0], @processed[1] = uMsg, result
141
+ } if handlers[:all]
142
+
143
+ handlers[Windows.HIWORD(wParam)].each { |handler|
144
+ (handler.arity == 0) ? handler.call : handler.call(args)
145
+
146
+ result = args[:result]; @processed[0], @processed[1] = uMsg, result
147
+ } if handlers[Windows.HIWORD(wParam)]
148
+ end
149
+
122
150
  result
123
151
  end
124
152
 
@@ -128,9 +156,20 @@ module Fzeet
128
156
  self
129
157
  end
130
158
 
159
+ def onCommand(cmd, notification = :all, &block)
160
+ (((@commands ||= {})[Command[cmd]] ||= {})[notification] ||= []) << block
161
+
162
+ self
163
+ end
164
+
131
165
  def on(*args, &block)
132
166
  case args.length
133
167
  when 1; onMessage(*args, &block)
168
+ when 2, 3
169
+ case Windows.const_get("WM_#{args.shift.upcase}")
170
+ when Windows::WM_COMMAND; onCommand(*args, &block)
171
+ else raise ArgumentError
172
+ end
134
173
  else raise ArgumentError
135
174
  end
136
175
  end
@@ -0,0 +1,49 @@
1
+ require_relative 'common'
2
+
3
+ module Fzeet
4
+ module WindowMethods
5
+ include Toggle
6
+
7
+ def show(cmdShow = :shownormal) Windows.ShowWindow(@handle, Windows.const_get("SW_#{cmdShow.upcase}")); self end
8
+ def update; Windows.DetonateLastError(0, :UpdateWindow, @handle); self end
9
+
10
+ def enabled?; Windows.IsWindowEnabled(@handle) != 0 end
11
+ def enabled=(enabled) Windows.EnableWindow(@handle, (enabled) ? 1 : 0) end
12
+
13
+ def [](id) Handle.instance(Windows.DetonateLastError(FFI::Pointer::NULL, :GetDlgItem, @handle, Command[id])) end
14
+
15
+ EnumChildProc = FFI::Function.new(:int, [:pointer, :long], convention: :stdcall) { |hwnd, lParam|
16
+ ObjectSpace._id2ref(lParam).call(Handle.instance(hwnd)) if Handle.instance?(hwnd); 1
17
+ }
18
+
19
+ def eachChild(&block) Windows.EnumChildWindows(@handle, EnumChildProc, block.object_id); self end
20
+
21
+ def sendmsg(msg, wParam = 0, lParam = 0)
22
+ Windows.SendMessage(
23
+ @handle,
24
+ Windows.const_get("WM_#{msg.upcase}"),
25
+ wParam.to_i,
26
+ ((lparam = lParam.to_i) > 0x7fff_ffff) ? lparam - 0x1_0000_0000 : lparam
27
+ )
28
+ end
29
+
30
+ def postmsg(msg, wParam = 0, lParam = 0)
31
+ Windows.DetonateLastError(0, :PostMessage,
32
+ @handle,
33
+ Windows.const_get("WM_#{msg.upcase}"),
34
+ wParam.to_i,
35
+ ((lparam = lParam.to_i) > 0x7fff_ffff) ? lparam - 0x1_0000_0000 : lparam
36
+ )
37
+
38
+ self
39
+ end
40
+
41
+ def menu; (Handle.instance?(handle = Windows.GetMenu(@handle))) ? Handle.instance(handle) : nil end
42
+
43
+ def menu=(menu)
44
+ self.menu.dispose if self.menu
45
+
46
+ Windows.DetonateLastError(0, :SetMenu, @handle, menu.handle) if menu
47
+ end
48
+ end
49
+ end
data/lib/fzeet/common.rb CHANGED
@@ -1,6 +1,23 @@
1
1
  require_relative 'windows'
2
2
 
3
3
  module Fzeet
4
+ module Toggle
5
+ def toggle(what) send("#{what}=", !send("#{what}?")); self end
6
+ end
7
+
8
+ class Command
9
+ @ids = {}
10
+ @nextId = Windows::WM_APP + 1
11
+
12
+ def self.[](id)
13
+ id = id.upcase
14
+
15
+ @ids[id], @nextId = @nextId, @nextId + 1 unless @ids.include?(id)
16
+
17
+ @ids[id]
18
+ end
19
+ end
20
+
4
21
  class DialogResult
5
22
  def initialize(id)
6
23
  @id = id
@@ -37,7 +54,7 @@ module Fzeet
37
54
  Windows.const_get("MB_ICON#{_opts[:icon].upcase}")
38
55
 
39
56
  DialogResult.new(
40
- Windows.MessageBox(_opts[:window] && _opts[:window].handle, message.to_s, _opts[:caption].to_s, flags)
57
+ Windows.DetonateLastError(0, :MessageBox, _opts[:window] && _opts[:window].handle, message.to_s, _opts[:caption].to_s, flags)
41
58
  )
42
59
  end
43
60
 
@@ -50,6 +67,15 @@ module Fzeet
50
67
 
51
68
  module_function :message, :question
52
69
 
70
+ class Message < Windows::MSG
71
+ def get!(window = nil, msgFilterMin = 0, msgFilterMax = 0)
72
+ Windows.DetonateLastError(-1, :GetMessage, self, window && window.handle, msgFilterMin, msgFilterMax) != 0
73
+ end
74
+
75
+ def translate; Windows.TranslateMessage(self); self end
76
+ def dispatch; Windows.DispatchMessage(self); self end
77
+ end
78
+
53
79
  class Handle
54
80
  @@instances = {}
55
81
 
@@ -69,4 +95,28 @@ module Fzeet
69
95
  def attach; @@instances[@handle.to_i] = self end
70
96
  def detach; @@instances.delete(@handle.to_i) end
71
97
  end
98
+
99
+ def using(o, cleanup = :dispose)
100
+ yield o
101
+ ensure
102
+ o.send(cleanup)
103
+ end
104
+
105
+ module_function :using
106
+
107
+ module FontMethods
108
+
109
+ end
110
+
111
+ class IndirectFont < Handle
112
+ include FontMethods
113
+
114
+ def initialize(logfont)
115
+ @handle = Windows.DetonateLastError(FFI::Pointer::NULL, :CreateFontIndirect, @logfont = logfont); attach
116
+ end
117
+
118
+ attr_reader :logfont
119
+
120
+ def dispose; Windows.DeleteObject(@handle); detach end
121
+ end
72
122
  end
@@ -8,5 +8,7 @@ module Fzeet
8
8
  DEFAULT_GUI_FONT = 17
9
9
 
10
10
  attach_function :GetStockObject, [:int], :pointer
11
+ attach_function :CreateFontIndirect, :CreateFontIndirectA, [:pointer], :pointer
12
+ attach_function :DeleteObject, [:pointer], :int
11
13
  end
12
14
  end
@@ -7,16 +7,6 @@ module Fzeet
7
7
 
8
8
  attach_function :GetLastError, [], :ulong
9
9
 
10
- def DetonateLastError(on, name, *args)
11
- raise "#{name} failed (last error #{GetLastError()})." if (failed = [*on].include?(result = send(name, *args)))
12
-
13
- result
14
- ensure
15
- yield failed if block_given?
16
- end
17
-
18
- module_function :DetonateLastError
19
-
20
10
  class ACTCTX < FFI::Struct
21
11
  layout \
22
12
  :cbSize, :ulong,
@@ -94,10 +94,16 @@ module Fzeet
94
94
  attach_function :ShowWindow, [:pointer, :int], :int
95
95
 
96
96
  attach_function :UpdateWindow, [:pointer], :int
97
+
98
+ attach_function :IsWindowEnabled, [:pointer], :int
97
99
  attach_function :EnableWindow, [:pointer, :int], :int
98
100
 
99
101
  attach_function :GetDlgItem, [:pointer, :int], :pointer
100
102
 
103
+ callback :WNDENUMPROC, [:pointer, :long], :int
104
+
105
+ attach_function :EnumChildWindows, [:pointer, :WNDENUMPROC, :long], :int
106
+
101
107
  attach_function :GetMenu, [:pointer], :pointer
102
108
  attach_function :SetMenu, [:pointer, :pointer], :int
103
109
 
@@ -105,13 +111,21 @@ module Fzeet
105
111
  attach_function :CreatePopupMenu, [], :pointer
106
112
  attach_function :DestroyMenu, [:pointer], :int
107
113
 
114
+ MF_SEPARATOR = 0x00000800
108
115
  MF_ENABLED = 0x00000000
109
116
  MF_GRAYED = 0x00000001
117
+ MF_UNCHECKED = 0x00000000
118
+ MF_CHECKED = 0x00000008
119
+ MF_USECHECKBITMAPS = 0x00000200
110
120
  MF_STRING = 0x00000000
111
121
  MF_POPUP = 0x00000010
122
+ MF_RIGHTJUSTIFY = 0x00004000
112
123
 
113
124
  attach_function :AppendMenu, :AppendMenuA, [:pointer, :uint, :uint, :string], :int
125
+ attach_function :GetMenuState, [:pointer, :uint, :uint], :uint
114
126
  attach_function :EnableMenuItem, [:pointer, :uint, :uint], :int
127
+ attach_function :CheckMenuItem, [:pointer, :uint, :uint], :ulong
128
+ attach_function :CheckMenuRadioItem, [:pointer, :uint, :uint, :uint, :uint], :int
115
129
 
116
130
  FVIRTKEY = 1
117
131
  FSHIFT = 0x04
@@ -160,5 +174,47 @@ module Fzeet
160
174
  attach_function :SendMessage, :SendMessageA, [:pointer, :uint, :uint, :long], :long
161
175
  attach_function :PostMessage, :PostMessageA, [:pointer, :uint, :uint, :long], :int
162
176
  attach_function :PostQuitMessage, [:int], :void
177
+
178
+ SPI_GETNONCLIENTMETRICS = 0x0029
179
+
180
+ class LOGFONT < FFI::Struct
181
+ layout \
182
+ :lfHeight, :long,
183
+ :lfWidth, :long,
184
+ :lfEscapement, :long,
185
+ :lfOrientation, :long,
186
+ :lfWeight, :long,
187
+ :lfItalic, :uchar,
188
+ :lfUnderline, :uchar,
189
+ :lfStrikeOut, :uchar,
190
+ :lfCharSet, :uchar,
191
+ :lfOutPrecision, :uchar,
192
+ :lfClipPrecision, :uchar,
193
+ :lfQuality, :uchar,
194
+ :lfPitchAndFamily, :uchar,
195
+ :lfFaceName, [:char, 32]
196
+ end
197
+
198
+ class NONCLIENTMETRICS < FFI::Struct
199
+ layout \
200
+ :cbSize, :uint,
201
+ :iBorderWidth, :int,
202
+ :iScrollWidth, :int,
203
+ :iScrollHeight, :int,
204
+ :iCaptionWidth, :int,
205
+ :iCaptionHeight, :int,
206
+ :lfCaptionFont, LOGFONT,
207
+ :iSmCaptionWidth, :int,
208
+ :iSmCaptionHeight, :int,
209
+ :lfSmCaptionFont, LOGFONT,
210
+ :iMenuWidth, :int,
211
+ :iMenuHeight, :int,
212
+ :lfMenuFont, LOGFONT,
213
+ :lfStatusFont, LOGFONT,
214
+ :lfMessageFont, LOGFONT,
215
+ :iPaddedBorderWidth, :int
216
+ end
217
+
218
+ attach_function :SystemParametersInfo, :SystemParametersInfoA, [:uint, :uint, :pointer, :uint], :int
163
219
  end
164
220
  end
data/lib/fzeet/windows.rb CHANGED
@@ -6,6 +6,16 @@ require_relative 'windows/gdi'
6
6
 
7
7
  module Fzeet
8
8
  module Windows
9
+ def DetonateLastError(on, name, *args)
10
+ raise "#{name} failed (last error #{GetLastError()})." if (failed = [*on].include?(result = send(name, *args)))
11
+
12
+ result
13
+ ensure
14
+ yield failed if block_given?
15
+ end
16
+
17
+ module_function :DetonateLastError
18
+
9
19
  COMMON_CONTROLS_ACTCTX = {handle: INVALID_HANDLE_VALUE, cookie: FFI::MemoryPointer.new(:ulong), activated: false}
10
20
 
11
21
  at_exit {
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fzeet
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 13
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 4
9
- - 0
10
- version: 0.4.0
9
+ - 1
10
+ version: 0.4.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Radoslav Peev
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-09 00:00:00 +03:00
18
+ date: 2010-08-13 00:00:00 +03:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -54,6 +54,7 @@ files:
54
54
  - lib/fzeet/Control.rb
55
55
  - lib/fzeet/Menu.rb
56
56
  - lib/fzeet/Window.rb
57
+ - lib/fzeet/WindowMethods.rb
57
58
  - lib/fzeet/windows.rb
58
59
  - lib/fzeet.rb
59
60
  - examples/Raw/Command.rbw
@@ -65,8 +66,10 @@ files:
65
66
  - examples/LifeCycle.rbw
66
67
  - examples/LifeCycle1.rbw
67
68
  - examples/LifeCycle2.rbw
69
+ - examples/LifeCycleNC.rbw
68
70
  - examples/MessageBox.rbw
69
71
  - examples/Minimal.rbw
72
+ - examples/Menu/Menu.rbw
70
73
  - LICENSE
71
74
  has_rdoc: true
72
75
  homepage: