fzeet 0.6.2 → 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|