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.
- data/LICENSE_Scintilla +20 -0
- data/examples/Control/Button1.rbw +7 -0
- data/examples/Control/Header.rbw +1 -1
- data/examples/Control/ListView.rbw +21 -3
- data/examples/Control/PropertySheet.rbw +2 -39
- data/examples/Control/Scintilla.rbw +20 -0
- data/examples/Control/Tab.rbw +18 -0
- data/examples/Control/TreeView.rbw +9 -22
- data/examples/Layout.rbw +23 -0
- data/examples/MDI.rbw +30 -0
- data/examples/UIRibbon/TabGroup.rbw +11 -6
- data/lib/fzeet/Application.rb +1 -0
- data/lib/fzeet/Common.rb +5 -3
- data/lib/fzeet/Control/Button.rb +12 -0
- data/lib/fzeet/Control/Common.rb +13 -5
- data/lib/fzeet/Control/Header.rb +24 -7
- data/lib/fzeet/Control/ListView.rb +45 -4
- data/lib/fzeet/Control/PropertySheet.rb +51 -0
- data/lib/fzeet/Control/Scintilla.rb +109 -0
- data/lib/fzeet/Control/Tab.rb +59 -0
- data/lib/fzeet/Control/TreeView.rb +50 -0
- data/lib/fzeet/Control.rb +3 -0
- data/lib/fzeet/Window/Common.rb +85 -3
- data/lib/fzeet/Window/Container.rb +29 -0
- data/lib/fzeet/Window/MDI.rb +30 -0
- data/lib/fzeet/Window/View.rb +1 -1
- data/lib/fzeet/Window/Window.rb +1 -1
- data/lib/fzeet/Window/WindowMethods.rb +13 -2
- data/lib/fzeet/Window.rb +2 -0
- data/lib/fzeet/windows/SciLexer.dll +0 -0
- data/lib/fzeet/windows/comctl/Tab.rb +88 -0
- data/lib/fzeet/windows/comctl.rb +1 -0
- data/lib/fzeet/windows/gdi.rb +2 -0
- data/lib/fzeet/windows/scintilla.rb +2279 -0
- data/lib/fzeet/windows/user/Message.rb +1 -0
- data/lib/fzeet/windows/user/Window.rb +39 -0
- data/lib/fzeet/windows.rb +6 -0
- metadata +21 -3
data/LICENSE_Scintilla
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
License for Scintilla and SciTE
|
2
|
+
|
3
|
+
Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
|
4
|
+
|
5
|
+
All Rights Reserved
|
6
|
+
|
7
|
+
Permission to use, copy, modify, and distribute this software and its
|
8
|
+
documentation for any purpose and without fee is hereby granted,
|
9
|
+
provided that the above copyright notice appear in all copies and that
|
10
|
+
both that copyright notice and this permission notice appear in
|
11
|
+
supporting documentation.
|
12
|
+
|
13
|
+
NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
14
|
+
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
15
|
+
AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY
|
16
|
+
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
17
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
18
|
+
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
19
|
+
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
|
20
|
+
OR PERFORMANCE OF THIS SOFTWARE.
|
data/examples/Control/Header.rbw
CHANGED
@@ -3,7 +3,7 @@ require 'fzeet'
|
|
3
3
|
include Fzeet
|
4
4
|
|
5
5
|
Application.run { |window| window.dialog = true
|
6
|
-
Header.new(window, :header1, style: :buttons,
|
6
|
+
Header.new(window, :header1, style: :buttons, height: 30, anchor: :ltr).
|
7
7
|
insertItem(0, 'Item1', 100).
|
8
8
|
insertItem(1, 'Item2', 100)
|
9
9
|
}
|
@@ -3,9 +3,27 @@ require 'fzeet'
|
|
3
3
|
include Fzeet
|
4
4
|
|
5
5
|
Application.run { |window| window.dialog = true
|
6
|
-
|
6
|
+
ascending = [true, true]
|
7
|
+
|
8
|
+
ListView.new(window, :listview1, style: :report, anchor: :ltrb).
|
7
9
|
tap { |lv| lv.xstyle << :gridlines << :fullrowselect }.
|
8
10
|
insertColumn(0, 'Column1', 100).insertColumn(1, 'Column2', 100).
|
9
|
-
insertItem(0, 0, '
|
10
|
-
insertItem(1, 0, '
|
11
|
+
insertItem(0, 0, 'Item5').insertItem(0, 1, 'Item2').
|
12
|
+
insertItem(1, 0, 'Item1').insertItem(1, 1, 'Item6').
|
13
|
+
insertItem(2, 0, 'Item3').insertItem(2, 1, 'Item4').
|
14
|
+
|
15
|
+
on(:columnclick) { |args|
|
16
|
+
lv, index = args[:sender], args[:index]
|
17
|
+
asc, header = ascending[index], lv.header
|
18
|
+
|
19
|
+
lv.sort(index) { |a, b| (asc) ? a.text <=> b.text : b.text <=> a.text }
|
20
|
+
|
21
|
+
header.count.times { |i|
|
22
|
+
style = (asc) ? :sortup : :sortdown if i == index
|
23
|
+
|
24
|
+
header.modifyItem(i, "Column#{i + 1}", style)
|
25
|
+
}
|
26
|
+
|
27
|
+
ascending[index] = !asc
|
28
|
+
}
|
11
29
|
}
|
@@ -2,49 +2,12 @@ require 'fzeet'
|
|
2
2
|
|
3
3
|
include Fzeet
|
4
4
|
|
5
|
-
pointers, pages = [], 3
|
6
|
-
|
7
5
|
Application.run { |window| window.dialog = true
|
8
|
-
psps = Class.new(FFI::Struct) {
|
9
|
-
layout \
|
10
|
-
:array, [Windows::PROPSHEETPAGE, pages]
|
11
|
-
}.new
|
12
|
-
|
13
|
-
dt = Windows::DLGTEMPLATE.new
|
14
|
-
|
15
|
-
dt[:style] = Fzeet.flags([:'3dlook', :control, :child, :tabstop], :ds_, :ws_)
|
16
|
-
dt[:x], dt[:y], dt[:cx], dt[:cy] = 100, 100, 300, 150
|
17
|
-
|
18
|
-
pages.times { |i|
|
19
|
-
psp = psps[:array][i]
|
20
|
-
|
21
|
-
psp[:dwSize] = psp.size
|
22
|
-
psp[:dwFlags] = Fzeet.flags([:dlgindirect, :usetitle], :psp_)
|
23
|
-
psp[:hInstance] = Windows.GetModuleHandle(nil)
|
24
|
-
psp[:template][:pResource] = dt
|
25
|
-
psp[:pszTitle] = pointers.push(FFI::MemoryPointer.from_string("Page#{i + 1}")).last
|
26
|
-
}
|
27
|
-
|
28
|
-
psh = Windows::PROPSHEETHEADER.new
|
29
|
-
|
30
|
-
psh[:dwSize] = psh.size
|
31
|
-
psh[:dwFlags] = Fzeet.flags(:propsheetpage, :psh_)
|
32
|
-
psh[:hwndParent] = window.handle
|
33
|
-
psh[:hInstance] = Windows.GetModuleHandle(nil)
|
34
|
-
psh[:pszCaption] = pointers.push(FFI::MemoryPointer.from_string('Sheet')).last
|
35
|
-
psh[:nPages] = pages
|
36
|
-
psh[:start][:nStartPage] = 1
|
37
|
-
psh[:pages][:ppsp] = psps
|
38
|
-
|
39
6
|
Button.new(window, :sheet, position: [10, 10, 76, 24]) {
|
40
|
-
|
7
|
+
PropertySheet.new(window)
|
41
8
|
}
|
42
9
|
|
43
10
|
Button.new(window, :wizard, position: [90, 10, 76, 24]) {
|
44
|
-
|
45
|
-
Windows.DetonateLastError(-1, :PropertySheet, psh)
|
46
|
-
psh[:dwFlags] &= ~Windows::PSH_WIZARD
|
11
|
+
PropertySheet.new(window, wizard: true)
|
47
12
|
}
|
48
|
-
|
49
|
-
window.on(:destroy) { pointers.each(&:free) }
|
50
13
|
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'fzeet'
|
2
|
+
|
3
|
+
include Fzeet
|
4
|
+
|
5
|
+
Application.run { |window|
|
6
|
+
Scintilla.new(window, :sci1, anchor: :ltrb).tap { |sci|
|
7
|
+
sci.focus = true
|
8
|
+
|
9
|
+
sci.font = 'Courier New'
|
10
|
+
sci.fontSize = 10
|
11
|
+
|
12
|
+
sci.tabWidth = 2
|
13
|
+
|
14
|
+
sci.text = <<-RUBY
|
15
|
+
def foo
|
16
|
+
42
|
17
|
+
end
|
18
|
+
RUBY
|
19
|
+
}
|
20
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'fzeet'
|
2
|
+
|
3
|
+
include Fzeet
|
4
|
+
|
5
|
+
Application.run { |window| window.dialog = true
|
6
|
+
Tab.new(window, :tab1, anchor: :ltrb).
|
7
|
+
insert('Tab1').
|
8
|
+
insert('Tab2').
|
9
|
+
insert('Tab3').
|
10
|
+
|
11
|
+
on(:selchanging) { |args|
|
12
|
+
args[:result] = 1 if question('Change?').no?
|
13
|
+
}.
|
14
|
+
|
15
|
+
on(:selchange) { |args|
|
16
|
+
message "Tab#{args[:sender].current.index + 1} selected"
|
17
|
+
}
|
18
|
+
}
|
@@ -3,26 +3,13 @@ require 'fzeet'
|
|
3
3
|
include Fzeet
|
4
4
|
|
5
5
|
Application.run { |window| window.dialog = true
|
6
|
-
TreeView.new(window, :treeview1, style: [:
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
tvis[:hParent] = Windows::TVI_ROOT
|
17
|
-
tvi[:pszText] = pointers.push(FFI::MemoryPointer.from_string('Foo')).last
|
18
|
-
hfoo = tv.sendmsg(:insertitem, 0, tvis.pointer)
|
19
|
-
tvis[:hParent] = hfoo
|
20
|
-
tvi[:pszText] = pointers.push(FFI::MemoryPointer.from_string('Baz')).last
|
21
|
-
hbaz = tv.sendmsg(:insertitem, 0, tvis.pointer)
|
22
|
-
|
23
|
-
tvis[:hParent] = Windows::TVI_ROOT
|
24
|
-
tvi[:pszText] = pointers.push(FFI::MemoryPointer.from_string('Bar')).last
|
25
|
-
hbar = tv.sendmsg(:insertitem, 0, tvis.pointer)
|
26
|
-
|
27
|
-
pointers.each(&:free)
|
6
|
+
TreeView.new(window, :treeview1, style: [:haslines, :linesatroot, :hasbuttons], anchor: :ltrb).
|
7
|
+
append('Foo').
|
8
|
+
append('Baz').
|
9
|
+
append('Quux').
|
10
|
+
parent. # Baz
|
11
|
+
parent. # Foo
|
12
|
+
append('Baz1').
|
13
|
+
root. # window[:treeview1]
|
14
|
+
append('Bar')
|
28
15
|
}
|
data/examples/Layout.rbw
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'fzeet'
|
2
|
+
|
3
|
+
include Fzeet
|
4
|
+
|
5
|
+
Application.run { |window|
|
6
|
+
Container.new(window, height: 100, anchor: :ltr).tap { |w|
|
7
|
+
w.style << :border
|
8
|
+
|
9
|
+
Button.new(w, :button1, position: [10, 10, 76, 24])
|
10
|
+
}
|
11
|
+
|
12
|
+
Container.new(window, height: 100, anchor: :lrb).tap { |w|
|
13
|
+
w.style << :border
|
14
|
+
|
15
|
+
Button.new(w, :button2, position: [10, 10, 76, 24])
|
16
|
+
|
17
|
+
Container.new(w, height: 50, anchor: :lrb).tap { |w1|
|
18
|
+
w1.style << :border
|
19
|
+
|
20
|
+
Button.new(w1, :button3, anchor: :ltrb)
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
data/examples/MDI.rbw
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'fzeet'
|
2
|
+
|
3
|
+
include Fzeet
|
4
|
+
|
5
|
+
Application.run(Frame.new) { |window|
|
6
|
+
children, total = [], 0
|
7
|
+
|
8
|
+
window.menu.
|
9
|
+
append(:popup, '&File', PopupMenu.new.
|
10
|
+
append(:string, '&New', :new)
|
11
|
+
)
|
12
|
+
|
13
|
+
window.
|
14
|
+
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
|
+
}.
|
19
|
+
|
20
|
+
on(:destroy) { |args| children.delete(args[:sender]) }
|
21
|
+
}.
|
22
|
+
|
23
|
+
on(:close) {
|
24
|
+
window.client.eachChild { |child|
|
25
|
+
# Ask each child if it's ok to close
|
26
|
+
}
|
27
|
+
|
28
|
+
window.dispose
|
29
|
+
}
|
30
|
+
}
|
@@ -5,19 +5,24 @@ include Fzeet
|
|
5
5
|
Application.run { |window|
|
6
6
|
UIRibbon.new(window).
|
7
7
|
on(:size) {
|
8
|
-
window[:edit1].position = 10, window.ribbon.height + 10,
|
8
|
+
window[:edit1].position = 10, window.ribbon.height + 10, 200, 18
|
9
9
|
}
|
10
10
|
|
11
11
|
Edit.new(window, :edit1, caption: '').
|
12
|
-
on(:setfocus) {
|
12
|
+
on(:setfocus) { |args|
|
13
13
|
window.ribbon.uif.SetUICommandProperty(CmdTabGroup1, Windows::UI_PKEY_ContextAvailable, Windows::PROPVARIANT[:int, 1])
|
14
|
-
}.
|
15
14
|
|
16
|
-
|
17
|
-
window.ribbon.uif.SetUICommandProperty(CmdTabGroup1, Windows::UI_PKEY_ContextAvailable, Windows::PROPVARIANT[:int, 0])
|
15
|
+
args[:sender].cuebanner = 'Now click outside...'
|
18
16
|
}.
|
19
17
|
|
20
18
|
cuebanner = 'Click here...'
|
21
19
|
|
22
|
-
window.on(:lbuttondown) {
|
20
|
+
window.on(:lbuttondown) {
|
21
|
+
window.ribbon.uif.SetUICommandProperty(CmdTabGroup1, Windows::UI_PKEY_ContextAvailable, Windows::PROPVARIANT[:int, 0])
|
22
|
+
|
23
|
+
if window[:edit1].focus?
|
24
|
+
window[:edit1].focus = false
|
25
|
+
window[:edit1].cuebanner = 'Click here...'
|
26
|
+
end
|
27
|
+
}
|
23
28
|
}
|
data/lib/fzeet/Application.rb
CHANGED
@@ -51,6 +51,7 @@ module Fzeet
|
|
51
51
|
|
52
52
|
while msg.get!
|
53
53
|
msg.translate.dispatch unless
|
54
|
+
(window.client && Windows.TranslateMDISysAccel(window.client.handle, msg) != 0) ||
|
54
55
|
accelerators.any? { |table| table.translate?(msg, @window) } ||
|
55
56
|
dialogs.any? { |dialog| dialog.dlgmsg?(msg) }
|
56
57
|
end
|
data/lib/fzeet/Common.rb
CHANGED
@@ -172,11 +172,11 @@ module Fzeet
|
|
172
172
|
def self.instance?(handle) @@instances.include?(handle.to_i) end
|
173
173
|
def self.instance(handle) raise "#{self}.#{__method__} failed." unless (instance = @@instances[handle.to_i]); instance end
|
174
174
|
|
175
|
-
def self.wrap(handle,
|
175
|
+
def self.wrap(handle, *ifaces)
|
176
176
|
Object.new.tap { |o|
|
177
177
|
o.instance_variable_set(:@handle, handle)
|
178
178
|
o.class.send(:attr_reader, :handle)
|
179
|
-
o.class.send(:include, iface)
|
179
|
+
ifaces.each { |iface| o.class.send(:include, iface) }
|
180
180
|
}
|
181
181
|
end
|
182
182
|
|
@@ -300,13 +300,15 @@ module Fzeet
|
|
300
300
|
holds.each { |hold| Windows.SelectObject(@handle, hold) }
|
301
301
|
end
|
302
302
|
|
303
|
+
def textExtent(text) Windows.DetonateLastError(0, :GetTextExtentPoint, @handle, text, text.length, s = Size.new); s end
|
304
|
+
|
303
305
|
def color; Windows.GetTextColor(@handle) end
|
304
306
|
def color=(color) Windows.SetTextColor(@handle, color) end
|
305
307
|
|
306
308
|
def background; Windows.GetBkColor(@handle) end
|
307
309
|
def background=(background) Windows.SetBkColor(@handle, background) end
|
308
310
|
|
309
|
-
def fillRect(rect, brush) Windows.DetonateLastError(0, :FillRect, @handle, rect, brush.handle); self end
|
311
|
+
def fillRect(rect, brush) Windows.DetonateLastError(0, :FillRect, @handle, rect, (brush.kind_of?(FFI::Pointer)) ? brush : brush.handle); self end
|
310
312
|
|
311
313
|
def text(text, rect, flags = 0) Windows.DetonateLastError(0, :DrawText, @handle, text, -1, rect, Fzeet.flags(flags, :dt_)); self end
|
312
314
|
|
data/lib/fzeet/Control/Button.rb
CHANGED
@@ -29,6 +29,18 @@ module Fzeet
|
|
29
29
|
def initialize(parent, id, opts = {}, &block)
|
30
30
|
super('Button', parent, id, opts)
|
31
31
|
|
32
|
+
width, height = 0, 0
|
33
|
+
|
34
|
+
using(ScreenDC.new) { |dc| dc.select(Font) {
|
35
|
+
minw = dc.textExtent('W' * 8).to_a[0]
|
36
|
+
width, height = dc.textExtent("W#{text}W").to_a
|
37
|
+
|
38
|
+
width = minw if width < minw; height = (height * 1.8).ceil
|
39
|
+
}}
|
40
|
+
|
41
|
+
self.location = 10, 10 if location.client!(parent).to_a == [0, 0]
|
42
|
+
self.size = width, height if size.to_a == [0, 0]
|
43
|
+
|
32
44
|
@parent.on(:command, @id, &block) if block
|
33
45
|
end
|
34
46
|
|
data/lib/fzeet/Control/Common.rb
CHANGED
@@ -32,11 +32,12 @@ module Fzeet
|
|
32
32
|
xstyle: [],
|
33
33
|
caption: id.capitalize,
|
34
34
|
style: [],
|
35
|
-
x:
|
36
|
-
y:
|
37
|
-
width:
|
38
|
-
height:
|
39
|
-
position: []
|
35
|
+
x: 0,
|
36
|
+
y: 0,
|
37
|
+
width: 0,
|
38
|
+
height: 0,
|
39
|
+
position: [],
|
40
|
+
anchor: nil
|
40
41
|
}
|
41
42
|
badopts = opts.keys - _opts.keys; raise "Bad option(s): #{badopts.join(', ')}." unless badopts.empty?
|
42
43
|
_opts.merge!(opts)
|
@@ -57,6 +58,13 @@ module Fzeet
|
|
57
58
|
sendmsg(:setfont, Font.handle, 1)
|
58
59
|
|
59
60
|
handlers.each { |k, v| on(k, &v) }
|
61
|
+
|
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 }
|
66
|
+
else raise ArgumentError, "Bad anchor spec: #{_opts[:anchor]}."
|
67
|
+
end if _opts[:anchor]
|
60
68
|
end
|
61
69
|
|
62
70
|
attr_reader :parent, :id
|
data/lib/fzeet/Control/Header.rb
CHANGED
@@ -2,6 +2,15 @@ require_relative 'Common'
|
|
2
2
|
|
3
3
|
module Fzeet
|
4
4
|
module HeaderMethods
|
5
|
+
Prefix = {
|
6
|
+
xstyle: [:ws_ex_],
|
7
|
+
style: [:hds_, :ws_],
|
8
|
+
message: [:hdm_, :ccm_, :wm_],
|
9
|
+
notification: [:hdn_, :nm_]
|
10
|
+
}
|
11
|
+
|
12
|
+
def count; sendmsg(:getitemcount) end
|
13
|
+
|
5
14
|
def insertItem(i, text, width)
|
6
15
|
hdi = Windows::HDITEM.new
|
7
16
|
|
@@ -17,18 +26,26 @@ module Fzeet
|
|
17
26
|
ensure
|
18
27
|
ptext.free
|
19
28
|
end
|
29
|
+
|
30
|
+
def modifyItem(i, text, style = 0)
|
31
|
+
hdi = Windows::HDITEM.new
|
32
|
+
|
33
|
+
hdi[:mask] = Fzeet.flags([:text, :format], :hdi_)
|
34
|
+
hdi[:pszText] = ptext = FFI::MemoryPointer.from_string(text)
|
35
|
+
hdi[:fmt] = Fzeet.flags([:left, :string], :hdf_)
|
36
|
+
hdi[:fmt] |= Fzeet.flags([*style].compact, :hdf_)
|
37
|
+
|
38
|
+
sendmsg(:setitem, i, hdi.pointer)
|
39
|
+
|
40
|
+
self
|
41
|
+
ensure
|
42
|
+
ptext.free
|
43
|
+
end
|
20
44
|
end
|
21
45
|
|
22
46
|
class Header < Control
|
23
47
|
include HeaderMethods
|
24
48
|
|
25
|
-
Prefix = {
|
26
|
-
xstyle: [:ws_ex_],
|
27
|
-
style: [:hds_, :ws_],
|
28
|
-
message: [:hdm_, :ccm_, :wm_],
|
29
|
-
notification: [:hdn_, :nm_]
|
30
|
-
}
|
31
|
-
|
32
49
|
def self.crackNotification(args) end
|
33
50
|
|
34
51
|
def initialize(parent, id, opts = {}, &block)
|
@@ -43,6 +43,12 @@ module Fzeet
|
|
43
43
|
ptext.free if ptext
|
44
44
|
end
|
45
45
|
|
46
|
+
class Item
|
47
|
+
def initialize(lvi) @subitems = [lvi] end
|
48
|
+
|
49
|
+
attr_reader :subitems
|
50
|
+
end
|
51
|
+
|
46
52
|
def insertItem(i, j, text)
|
47
53
|
lvi = Windows::LVITEM.new
|
48
54
|
|
@@ -51,16 +57,39 @@ module Fzeet
|
|
51
57
|
lvi[:iSubItem] = j
|
52
58
|
lvi[:pszText] = ptext = FFI::MemoryPointer.from_string(text)
|
53
59
|
|
54
|
-
if j
|
55
|
-
|
56
|
-
|
60
|
+
if j == 0
|
61
|
+
@items << Item.new(lvi)
|
62
|
+
|
63
|
+
lvi[:mask] |= Windows::LVIF_PARAM
|
64
|
+
lvi[:lParam] = @items[i].object_id
|
65
|
+
|
57
66
|
sendmsg(:insertitem, 0, lvi.pointer)
|
67
|
+
else
|
68
|
+
@items[i].subitems << lvi
|
69
|
+
|
70
|
+
sendmsg(:setitem, 0, lvi.pointer)
|
71
|
+
end
|
72
|
+
|
73
|
+
@items[i].subitems[j].instance_variable_set(:@text, text)
|
74
|
+
|
75
|
+
class << @items[i].subitems[j]
|
76
|
+
attr_reader :text
|
58
77
|
end
|
59
78
|
|
60
79
|
self
|
61
80
|
ensure
|
62
81
|
ptext.free if ptext
|
63
82
|
end
|
83
|
+
|
84
|
+
def sort(j = 0)
|
85
|
+
sendmsg(:sortitems, j,
|
86
|
+
FFI::Function.new(:int, [:long, :long, :long], convention: :stdcall) { |lParam1, lParam2, lParamSort|
|
87
|
+
yield ObjectSpace._id2ref(lParam1).subitems[lParamSort], ObjectSpace._id2ref(lParam2).subitems[lParamSort], j
|
88
|
+
}
|
89
|
+
)
|
90
|
+
|
91
|
+
self
|
92
|
+
end
|
64
93
|
end
|
65
94
|
|
66
95
|
class ListView < Control
|
@@ -73,14 +102,26 @@ module Fzeet
|
|
73
102
|
notification: [:lvn_, :nm_]
|
74
103
|
}
|
75
104
|
|
76
|
-
def self.crackNotification(args)
|
105
|
+
def self.crackNotification(args)
|
106
|
+
case args[:notification]
|
107
|
+
when Windows::LVN_COLUMNCLICK
|
108
|
+
args[:nmlv] = Windows::NMLISTVIEW.new(FFI::Pointer.new(args[:lParam]))
|
109
|
+
args[:index] = args[:nmlv][:iSubItem]
|
110
|
+
end
|
111
|
+
end
|
77
112
|
|
78
113
|
def initialize(parent, id, opts = {}, &block)
|
79
114
|
super('SysListView32', parent, id, opts)
|
80
115
|
|
116
|
+
@header = Handle.wrap(FFI::Pointer.new(sendmsg(:getheader)), WindowMethods, HeaderMethods)
|
117
|
+
|
118
|
+
@items = []
|
119
|
+
|
81
120
|
@parent.on(:notify, @id, &block) if block
|
82
121
|
end
|
83
122
|
|
123
|
+
attr_reader :header, :items
|
124
|
+
|
84
125
|
def on(notification, &block)
|
85
126
|
@parent.on(:notify, @id, Fzeet.constant(notification, *self.class::Prefix[:notification]), &block)
|
86
127
|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative 'Common'
|
2
|
+
|
3
|
+
module Fzeet
|
4
|
+
class PropertyPage
|
5
|
+
class PROPSHEETPAGEA1 < FFI::Struct
|
6
|
+
layout \
|
7
|
+
:array, [Windows::PROPSHEETPAGE, 1]
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class PropertySheet
|
16
|
+
def initialize(parent, opts = {wizard: false})
|
17
|
+
pointers = []
|
18
|
+
|
19
|
+
psps = PropertyPage::PROPSHEETPAGEA1.new
|
20
|
+
|
21
|
+
dt = Windows::DLGTEMPLATE.new
|
22
|
+
|
23
|
+
dt[:style] = Fzeet.flags([:'3dlook', :control, :child, :tabstop], :ds_, :ws_)
|
24
|
+
dt[:x], dt[:y], dt[:cx], dt[:cy] = 100, 100, 300, 150
|
25
|
+
|
26
|
+
psp = psps[:array][0]
|
27
|
+
|
28
|
+
psp[:dwSize] = psp.size
|
29
|
+
psp[:dwFlags] = Fzeet.flags([:dlgindirect, :usetitle], :psp_)
|
30
|
+
psp[:hInstance] = Windows.GetModuleHandle(nil)
|
31
|
+
psp[:template][:pResource] = dt
|
32
|
+
psp[:pszTitle] = pointers.push(FFI::MemoryPointer.from_string("Page")).last
|
33
|
+
|
34
|
+
psh = Windows::PROPSHEETHEADER.new
|
35
|
+
|
36
|
+
psh[:dwSize] = psh.size
|
37
|
+
psh[:dwFlags] = Fzeet.flags(:propsheetpage, :psh_)
|
38
|
+
psh[:dwFlags] |= Windows::PSH_WIZARD if opts[:wizard]
|
39
|
+
psh[:hwndParent] = parent.handle
|
40
|
+
psh[:hInstance] = Windows.GetModuleHandle(nil)
|
41
|
+
psh[:pszCaption] = pointers.push(FFI::MemoryPointer.from_string('Sheet')).last
|
42
|
+
psh[:nPages] = 1
|
43
|
+
psh[:start][:nStartPage] = 0
|
44
|
+
psh[:pages][:ppsp] = psps
|
45
|
+
|
46
|
+
Windows.DetonateLastError(-1, :PropertySheet, psh)
|
47
|
+
ensure
|
48
|
+
pointers.each(&:free)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require_relative 'Common'
|
2
|
+
|
3
|
+
module Fzeet
|
4
|
+
module ScintillaMethods
|
5
|
+
def text
|
6
|
+
FFI::MemoryPointer.new(:uchar, len = sendmsg(:gettextlength) + 1) { |p|
|
7
|
+
sendmsg(:gettext, len, p)
|
8
|
+
|
9
|
+
return p.read_string
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def text=(text)
|
14
|
+
p = FFI::MemoryPointer.from_string(text)
|
15
|
+
|
16
|
+
sendmsg(:settext, 0, p)
|
17
|
+
ensure
|
18
|
+
p.free
|
19
|
+
end
|
20
|
+
|
21
|
+
def font
|
22
|
+
FFI::MemoryPointer.new(:uchar, 33) { |p|
|
23
|
+
sendmsg(:stylegetfont, Windows::STYLE_DEFAULT, p)
|
24
|
+
|
25
|
+
return p.read_string
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def font=(name)
|
30
|
+
p = FFI::MemoryPointer.from_string(name)
|
31
|
+
|
32
|
+
sendmsg(:stylesetfont, Windows::STYLE_DEFAULT, p)
|
33
|
+
ensure
|
34
|
+
p.free
|
35
|
+
end
|
36
|
+
|
37
|
+
def fontSize; sendmsg(:stylegetsize, Windows::STYLE_DEFAULT) end
|
38
|
+
def fontSize=(size) sendmsg(:stylesetsize, Windows::STYLE_DEFAULT, size) end
|
39
|
+
|
40
|
+
def tabWidth; sendmsg(:gettabwidth) end
|
41
|
+
def tabWidth=(tabWidth) sendmsg(:settabwidth, tabWidth) end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Scintilla < Control
|
45
|
+
include ScintillaMethods
|
46
|
+
|
47
|
+
Prefix = {
|
48
|
+
xstyle: [:ws_ex_],
|
49
|
+
style: [:ws_],
|
50
|
+
message: [:sci_, :wm_],
|
51
|
+
notification: [:scn_, :scen_, :nm_]
|
52
|
+
}
|
53
|
+
|
54
|
+
def self.crackNotification(args)
|
55
|
+
case args[:notification]
|
56
|
+
when \
|
57
|
+
Windows::SCN_STYLENEEDED,
|
58
|
+
Windows::SCN_CHARADDED,
|
59
|
+
Windows::SCN_SAVEPOINTREACHED,
|
60
|
+
Windows::SCN_SAVEPOINTLEFT,
|
61
|
+
Windows::SCN_MODIFYATTEMPTRO,
|
62
|
+
Windows::SCN_KEY,
|
63
|
+
Windows::SCN_DOUBLECLICK,
|
64
|
+
Windows::SCN_UPDATEUI,
|
65
|
+
Windows::SCN_MODIFIED,
|
66
|
+
Windows::SCN_MACRORECORD,
|
67
|
+
Windows::SCN_MARGINCLICK,
|
68
|
+
Windows::SCN_NEEDSHOWN,
|
69
|
+
Windows::SCN_PAINTED,
|
70
|
+
Windows::SCN_USERLISTSELECTION,
|
71
|
+
Windows::SCN_URIDROPPED,
|
72
|
+
Windows::SCN_DWELLSTART,
|
73
|
+
Windows::SCN_DWELLEND,
|
74
|
+
Windows::SCN_ZOOM,
|
75
|
+
Windows::SCN_HOTSPOTCLICK,
|
76
|
+
Windows::SCN_HOTSPOTDOUBLECLICK,
|
77
|
+
Windows::SCN_CALLTIPCLICK,
|
78
|
+
Windows::SCN_AUTOCSELECTION,
|
79
|
+
Windows::SCN_INDICATORCLICK,
|
80
|
+
Windows::SCN_INDICATORRELEASE,
|
81
|
+
Windows::SCN_AUTOCCANCELLED,
|
82
|
+
Windows::SCN_AUTOCCHARDELETED
|
83
|
+
|
84
|
+
args[:scn] = Windows::SCNotification.new(FFI::Pointer.new(args[:lParam]))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def initialize(parent, id, opts = {}, &block)
|
89
|
+
super('Scintilla', parent, id, opts)
|
90
|
+
|
91
|
+
@parent.on(:notify, @id, &block) if block
|
92
|
+
end
|
93
|
+
|
94
|
+
def on(notification, &block)
|
95
|
+
case c = Fzeet.constant(notification, *self.class::Prefix[:notification])
|
96
|
+
when \
|
97
|
+
Windows::SCEN_CHANGE,
|
98
|
+
Windows::SCEN_SETFOCUS,
|
99
|
+
Windows::SCEN_KILLFOCUS
|
100
|
+
|
101
|
+
@parent.on(:command, @id, c, &block)
|
102
|
+
else
|
103
|
+
@parent.on(:notify, @id, c, &block)
|
104
|
+
end
|
105
|
+
|
106
|
+
self
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|