fzeet 0.6.2 → 0.6.3

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,59 @@
1
+ require_relative 'Common'
2
+
3
+ module Fzeet
4
+ module TabMethods
5
+ class Item
6
+ def initialize(tab, i) @tab, @index = tab, i end
7
+
8
+ attr_reader :tab, :index
9
+ end
10
+
11
+ def [](i) Item.new(self, i) end
12
+
13
+ def count; sendmsg(:getitemcount) end
14
+ alias :size :count
15
+ alias :length :count
16
+
17
+ def insert(text, i = count)
18
+ tci = Windows::TCITEM.new
19
+
20
+ tci[:mask] = Fzeet.flags(:text, :tcif_)
21
+ tci[:pszText] = ptext = FFI::MemoryPointer.from_string(text)
22
+
23
+ sendmsg(:insertitem, i, tci.pointer)
24
+
25
+ self
26
+ ensure
27
+ ptext.free
28
+ end
29
+
30
+ def current; self[sendmsg(:getcursel)] end
31
+ end
32
+
33
+ class Tab < Control
34
+ include TabMethods
35
+
36
+ Prefix = {
37
+ xstyle: [:tcs_ex_, :ws_ex_],
38
+ style: [:tcs_, :ws_],
39
+ message: [:tcm_, :ccm_, :wm_],
40
+ notification: [:tcn_, :nm_]
41
+ }
42
+
43
+ def self.crackNotification(args) end
44
+
45
+ def initialize(parent, id, opts = {}, &block)
46
+ super('SysTabControl32', parent, id, opts)
47
+
48
+ style << :clipsiblings
49
+
50
+ @parent.on(:notify, @id, &block) if block
51
+ end
52
+
53
+ def on(notification, &block)
54
+ @parent.on(:notify, @id, Fzeet.constant(notification, *self.class::Prefix[:notification]), &block)
55
+
56
+ self
57
+ end
58
+ end
59
+ end
@@ -2,7 +2,57 @@ require_relative 'Common'
2
2
 
3
3
  module Fzeet
4
4
  module TreeViewMethods
5
+ class Item
6
+ def initialize(text) @text = text end
5
7
 
8
+ attr_reader :text, :root, :parent, :handle
9
+
10
+ def root=(root) raise 'Can\'t change established @root.' if @root; @root = root end
11
+ def parent=(parent) raise 'Can\'t change established @parent.' if @parent; @parent = parent end
12
+ def handle=(handle) raise 'Can\'t change established @handle.' if @handle; @handle = handle end
13
+
14
+ def append(text)
15
+ item = Item.new(text)
16
+
17
+ tvis = Windows::TVINSERTSTRUCT.new
18
+
19
+ tvis[:hInsertAfter] = Windows::TVI_LAST
20
+ tvis[:hParent] = @handle
21
+
22
+ tvi = tvis[:item]
23
+
24
+ tvi[:mask] = Windows::TVIF_TEXT
25
+ tvi[:pszText] = ptext = FFI::MemoryPointer.from_string(item.text)
26
+
27
+ item.root, item.parent = @root, self
28
+ item.handle = @root.sendmsg(:insertitem, 0, tvis.pointer)
29
+
30
+ item
31
+ ensure
32
+ ptext.free
33
+ end
34
+ end
35
+
36
+ def append(text)
37
+ item = Item.new(text)
38
+
39
+ tvis = Windows::TVINSERTSTRUCT.new
40
+
41
+ tvis[:hInsertAfter] = Windows::TVI_LAST
42
+ tvis[:hParent] = Windows::TVI_ROOT
43
+
44
+ tvi = tvis[:item]
45
+
46
+ tvi[:mask] = Windows::TVIF_TEXT
47
+ tvi[:pszText] = ptext = FFI::MemoryPointer.from_string(item.text)
48
+
49
+ item.root, item.parent = self, self
50
+ item.handle = sendmsg(:insertitem, 0, tvis.pointer)
51
+
52
+ item
53
+ ensure
54
+ ptext.free
55
+ end
6
56
  end
7
57
 
8
58
  class TreeView < Control
data/lib/fzeet/Control.rb CHANGED
@@ -2,6 +2,7 @@ require_relative 'Control/Button'
2
2
  require_relative 'Control/SysLink' if Fzeet::Windows::WINVER.AtLeastWindowsXP?
3
3
  require_relative 'Control/Static'
4
4
  require_relative 'Control/Edit'
5
+ require_relative 'Control/Scintilla'
5
6
  require_relative 'Control/UpDown'
6
7
  require_relative 'Control/MonthCalendar'
7
8
  require_relative 'Control/DateTimePicker'
@@ -12,3 +13,5 @@ require_relative 'Control/Header'
12
13
  require_relative 'Control/ListView'
13
14
  require_relative 'Control/TreeView'
14
15
  require_relative 'Control/ProgressBar'
16
+ require_relative 'Control/PropertySheet'
17
+ require_relative 'Control/Tab'
@@ -87,6 +87,80 @@ module Fzeet
87
87
  result || Windows.DefWindowProc(hwnd, uMsg, wParam, lParam)
88
88
  }
89
89
 
90
+ FrameProc = FFI::Function.new(:long, [:pointer, :uint, :uint, :long], convention: :stdcall) { |hwnd, uMsg, wParam, lParam|
91
+ begin
92
+ if uMsg == Windows::WM_NCCREATE
93
+ @@instances[hwnd.to_i] = ObjectSpace._id2ref(
94
+ Windows::CREATESTRUCT.new(FFI::Pointer.new(lParam))[:lpCreateParams].to_i
95
+ )
96
+
97
+ @@instances[hwnd.to_i].instance_variable_set(:@handle, hwnd)
98
+ end
99
+
100
+ if uMsg == Windows::WM_CREATE
101
+ @@instances[hwnd.to_i].menu = Menu.new.
102
+ append(:popup, '&Window', PopupMenu.new)
103
+
104
+ ccs = Windows::CLIENTCREATESTRUCT.new
105
+
106
+ ccs[:hWindowMenu] = @@instances[hwnd.to_i].menu.submenus[0].handle
107
+ ccs[:idFirstChild] = 50000
108
+
109
+ hwndClient = Windows.DetonateLastError(FFI::Pointer::NULL, :CreateWindowEx,
110
+ 0, 'MDIClient', nil, Fzeet.flags([:child, :clipsiblings, :clipchildren, :visible], :ws_),
111
+ 0, 0, 0, 0,
112
+ hwnd, nil, Windows.GetModuleHandle(nil), ccs
113
+ )
114
+
115
+ @@instances[hwnd.to_i].instance_variable_set(:@client, Handle.wrap(hwndClient, WindowMethods))
116
+ end
117
+
118
+ result = @@instances[hwnd.to_i].windowProc(hwnd, uMsg, wParam, lParam) if @@instances[hwnd.to_i]
119
+ rescue
120
+ answer = Fzeet.message %Q{#{$!}\n\n#{$!.backtrace.join("\n")}}, buttons: [:abort, :retry, :ignore], icon: :error
121
+
122
+ Application.quit if answer.abort?
123
+ ensure
124
+ if uMsg == Windows::WM_NCDESTROY
125
+ @@instances[hwnd.to_i].dialog = false
126
+
127
+ @@instances.delete(hwnd.to_i)
128
+ end
129
+ end
130
+
131
+ hwndClient = @@instances[hwnd.to_i] && @@instances[hwnd.to_i].client && @@instances[hwnd.to_i].client.handle
132
+
133
+ result || Windows.DefFrameProc(hwnd, hwndClient, uMsg, wParam, lParam)
134
+ }
135
+
136
+ MDIChildProc = FFI::Function.new(:long, [:pointer, :uint, :uint, :long], convention: :stdcall) { |hwnd, uMsg, wParam, lParam|
137
+ begin
138
+ if uMsg == Windows::WM_NCCREATE
139
+ @@instances[hwnd.to_i] = ObjectSpace._id2ref(
140
+ Windows::MDICREATESTRUCT.new(
141
+ Windows::CREATESTRUCT.new(FFI::Pointer.new(lParam))[:lpCreateParams]
142
+ )[:lParam]
143
+ )
144
+
145
+ @@instances[hwnd.to_i].instance_variable_set(:@handle, hwnd)
146
+ end
147
+
148
+ result = @@instances[hwnd.to_i].windowProc(hwnd, uMsg, wParam, lParam) if @@instances[hwnd.to_i]
149
+ rescue
150
+ answer = Fzeet.message %Q{#{$!}\n\n#{$!.backtrace.join("\n")}}, buttons: [:abort, :retry, :ignore], icon: :error
151
+
152
+ Application.quit if answer.abort?
153
+ ensure
154
+ if uMsg == Windows::WM_NCDESTROY
155
+ @@instances[hwnd.to_i].dialog = false
156
+
157
+ @@instances.delete(hwnd.to_i)
158
+ end
159
+ end
160
+
161
+ result || Windows.DefMDIChildProc(hwnd, uMsg, wParam, lParam)
162
+ }
163
+
90
164
  DialogProc = FFI::Function.new(:int, [:pointer, :uint, :uint, :long], convention: :stdcall) { |hwnd, uMsg, wParam, lParam|
91
165
  begin
92
166
  if uMsg == Windows::WM_INITDIALOG
@@ -173,9 +247,10 @@ module Fzeet
173
247
  y: Windows::CW_USEDEFAULT,
174
248
  width: Windows::CW_USEDEFAULT,
175
249
  height: Windows::CW_USEDEFAULT,
176
- position: [],
177
250
  parent: nil,
178
- menu: nil
251
+ menu: nil,
252
+ position: [],
253
+ anchor: nil
179
254
  }
180
255
  badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
181
256
  _opts.merge!(opts)
@@ -213,10 +288,17 @@ module Fzeet
213
288
 
214
289
  eachChild(&:dispose)
215
290
  }
291
+
292
+ case _opts[:anchor]
293
+ when :ltr; @parent.on(:size) { self.position = @parent.rect.tap { |r| r[:bottom] = _opts[:height] }.to_a }
294
+ when :lrb; @parent.on(:size) { self.position = @parent.rect.tap { |r| r[:top] = r[:bottom] - _opts[:height]; r[:bottom] = _opts[:height] }.to_a }
295
+ when :ltrb; @parent.on(:size) { self.position = @parent.rect.to_a }
296
+ else raise ArgumentError, "Bad anchor spec: #{_opts[:anchor]}."
297
+ end if _opts[:anchor] && @parent
216
298
  end
217
299
  end
218
300
 
219
- attr_reader :parent, :ribbon
301
+ attr_reader :parent, :client, :ribbon
220
302
 
221
303
  def dispose; Windows.DestroyWindow(@handle) end
222
304
 
@@ -0,0 +1,29 @@
1
+ require_relative 'Common'
2
+
3
+ module Fzeet
4
+ Container = BasicWindow['Fzeet.Container']
5
+
6
+ class Container
7
+ def initialize(parent, opts = {})
8
+ opts[:parent] = parent
9
+ (opts[:style] ||= []) << :visible << :child << :clipsiblings << :clipchildren
10
+
11
+ super(opts)
12
+
13
+ style >> :caption >> :thickframe
14
+
15
+ on(:erasebkgnd) { |args|
16
+ Handle.wrap(FFI::Pointer.new(args[:wParam]), DCMethods).
17
+ fillRect(
18
+ rect,
19
+ case @parent
20
+ when Dialog; FFI::Pointer.new(Windows::CTLCOLOR_DLG + 1)
21
+ when BasicWindow; FFI::Pointer.new(Windows.DetonateLastError(-1, :GetClassLong, @parent.handle, Windows::GCL_HBRBACKGROUND))
22
+ end
23
+ )
24
+
25
+ args[:result] = 1
26
+ }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ require_relative 'Common'
2
+
3
+ module Fzeet
4
+ Frame = BasicWindow['Fzeet.Frame',
5
+ wndProc: BasicWindow::FrameProc,
6
+ background: SystemBrush.new(:appworkspace)
7
+ ]
8
+
9
+ class Frame
10
+ def initialize(opts = {})
11
+ (opts[:style] ||= []) << :overlappedwindow << :clipsiblings << :clipchildren
12
+
13
+ super
14
+ end
15
+ end
16
+
17
+ MDIChild = BasicWindow['Fzeet.MDIChild',
18
+ wndProc: BasicWindow::MDIChildProc
19
+ ]
20
+
21
+ class MDIChild
22
+ def initialize(parent, opts = {})
23
+ (opts[:xstyle] ||= []) << :mdichild
24
+ (opts[:style] ||= []) << :child << :overlappedwindow << :clipsiblings << :clipchildren << :visible
25
+ opts[:parent] = parent
26
+
27
+ super(opts)
28
+ end
29
+ end
30
+ end
@@ -7,7 +7,7 @@ module Fzeet
7
7
 
8
8
  class View
9
9
  def initialize(opts = {})
10
- (opts[:style] ||= []) << :overlappedwindow << :clipchildren
10
+ (opts[:style] ||= []) << :overlappedwindow << :clipsiblings << :clipchildren
11
11
 
12
12
  super
13
13
  end
@@ -5,7 +5,7 @@ module Fzeet
5
5
 
6
6
  class Window
7
7
  def initialize(opts = {})
8
- (opts[:style] ||= []) << :overlappedwindow << :clipchildren
8
+ (opts[:style] ||= []) << :overlappedwindow << :clipsiblings << :clipchildren
9
9
 
10
10
  super
11
11
  end
@@ -4,8 +4,19 @@ module Fzeet
4
4
  module WindowMethods
5
5
  include Toggle
6
6
 
7
- def message(message, opts = {window: self}) Fzeet.message(message, opts) end
8
- def question(message, opts = {window: self}) Fzeet.question(message, opts) end
7
+ def message(message, opts = {})
8
+ opts[:window] ||= self
9
+ opts[:caption] ||= text
10
+
11
+ Fzeet.message(message, opts)
12
+ end
13
+
14
+ def question(message, opts = {})
15
+ opts[:window] ||= self
16
+ opts[:caption] ||= text
17
+
18
+ Fzeet.question(message, opts)
19
+ end
9
20
 
10
21
  def sendmsg(msg, wParam = 0, lParam = 0)
11
22
  Windows.SendMessage(
data/lib/fzeet/Window.rb CHANGED
@@ -1,3 +1,5 @@
1
1
  require_relative 'Window/Window'
2
2
  require_relative 'Window/View'
3
+ require_relative 'Window/Container'
4
+ require_relative 'Window/MDI'
3
5
  require_relative 'Window/Dialog'
Binary file
@@ -0,0 +1,88 @@
1
+ require_relative 'Common'
2
+
3
+ module Fzeet
4
+ module Windows
5
+ TCS_SCROLLOPPOSITE = 0x0001
6
+ TCS_BOTTOM = 0x0002
7
+ TCS_RIGHT = 0x0002
8
+ TCS_MULTISELECT = 0x0004
9
+ TCS_FLATBUTTONS = 0x0008
10
+ TCS_FORCEICONLEFT = 0x0010
11
+ TCS_FORCELABELLEFT = 0x0020
12
+ TCS_HOTTRACK = 0x0040
13
+ TCS_VERTICAL = 0x0080
14
+ TCS_TABS = 0x0000
15
+ TCS_BUTTONS = 0x0100
16
+ TCS_SINGLELINE = 0x0000
17
+ TCS_MULTILINE = 0x0200
18
+ TCS_RIGHTJUSTIFY = 0x0000
19
+ TCS_FIXEDWIDTH = 0x0400
20
+ TCS_RAGGEDRIGHT = 0x0800
21
+ TCS_FOCUSONBUTTONDOWN = 0x1000
22
+ TCS_OWNERDRAWFIXED = 0x2000
23
+ TCS_TOOLTIPS = 0x4000
24
+ TCS_FOCUSNEVER = 0x8000
25
+
26
+ TCS_EX_FLATSEPARATORS = 0x00000001
27
+ TCS_EX_REGISTERDROP = 0x00000002
28
+
29
+ TCM_FIRST = 0x1300
30
+ TCM_GETIMAGELIST = TCM_FIRST + 2
31
+ TCM_SETIMAGELIST = TCM_FIRST + 3
32
+ TCM_GETITEMCOUNT = TCM_FIRST + 4
33
+ TCM_GETITEM = TCM_FIRST + 5
34
+ TCM_SETITEM = TCM_FIRST + 6
35
+ TCM_INSERTITEM = TCM_FIRST + 7
36
+ TCM_DELETEITEM = TCM_FIRST + 8
37
+ TCM_DELETEALLITEMS = TCM_FIRST + 9
38
+ TCM_GETITEMRECT = TCM_FIRST + 10
39
+ TCM_GETCURSEL = TCM_FIRST + 11
40
+ TCM_SETCURSEL = TCM_FIRST + 12
41
+ TCM_HITTEST = TCM_FIRST + 13
42
+ TCM_SETITEMEXTRA = TCM_FIRST + 14
43
+ TCM_ADJUSTRECT = TCM_FIRST + 40
44
+ TCM_SETITEMSIZE = TCM_FIRST + 41
45
+ TCM_REMOVEIMAGE = TCM_FIRST + 42
46
+ TCM_SETPADDING = TCM_FIRST + 43
47
+ TCM_GETROWCOUNT = TCM_FIRST + 44
48
+ TCM_GETTOOLTIPS = TCM_FIRST + 45
49
+ TCM_SETTOOLTIPS = TCM_FIRST + 46
50
+ TCM_GETCURFOCUS = TCM_FIRST + 47
51
+ TCM_SETCURFOCUS = TCM_FIRST + 48
52
+ TCM_SETMINTABWIDTH = TCM_FIRST + 49
53
+ TCM_DESELECTALL = TCM_FIRST + 50
54
+ TCM_HIGHLIGHTITEM = TCM_FIRST + 51
55
+ TCM_SETEXTENDEDSTYLE = TCM_FIRST + 52
56
+ TCM_GETEXTENDEDSTYLE = TCM_FIRST + 53
57
+ TCM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT
58
+ TCM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT
59
+
60
+ TCN_FIRST = 0x1_0000_0000 - 550
61
+ TCN_LAST = 0x1_0000_0000 - 580
62
+ TCN_KEYDOWN = TCN_FIRST - 0
63
+ TCN_SELCHANGE = TCN_FIRST - 1
64
+ TCN_SELCHANGING = TCN_FIRST - 2
65
+ TCN_GETOBJECT = TCN_FIRST - 3
66
+ TCN_FOCUSCHANGE = TCN_FIRST - 4
67
+
68
+ TCIF_TEXT = 0x0001
69
+ TCIF_IMAGE = 0x0002
70
+ TCIF_RTLREADING = 0x0004
71
+ TCIF_PARAM = 0x0008
72
+ TCIF_STATE = 0x0010
73
+
74
+ TCIS_BUTTONPRESSED = 0x0001
75
+ TCIS_HIGHLIGHTED = 0x0002
76
+
77
+ class TCITEM < FFI::Struct
78
+ layout \
79
+ :mask, :uint,
80
+ :dwState, :ulong,
81
+ :dwStateMask, :ulong,
82
+ :pszText, :pointer,
83
+ :cchTextMax, :int,
84
+ :iImage, :int,
85
+ :lParam, :long
86
+ end
87
+ end
88
+ end
@@ -11,3 +11,4 @@ require_relative 'comctl/ListView'
11
11
  require_relative 'comctl/TreeView'
12
12
  require_relative 'comctl/ProgressBar'
13
13
  require_relative 'comctl/PropertySheet'
14
+ require_relative 'comctl/Tab'
@@ -48,6 +48,8 @@ module Fzeet
48
48
 
49
49
  attach_function :SelectObject, [:pointer, :pointer], :pointer
50
50
 
51
+ attach_function :GetTextExtentPoint, :GetTextExtentPointA, [:pointer, :string, :int, :pointer], :int
52
+
51
53
  attach_function :GetTextColor, [:pointer], :ulong
52
54
  attach_function :SetTextColor, [:pointer, :ulong], :ulong
53
55