fzeet 0.4.0 → 0.4.1

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 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: