-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathlistview.go
More file actions
141 lines (123 loc) · 4.19 KB
/
listview.go
File metadata and controls
141 lines (123 loc) · 4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package wingui
import (
"syscall"
"unsafe"
"github.com/lxn/win"
)
// ListView is a wrapper for the Win32 SysListView32 control.
// Notes:
// - Most notifications are delivered as WM_NOTIFY to the parent dialog (routed by Dialog.dialogWndProc).
// - For report view with columns, prefer creating the control with LVS_REPORT style in resources.
type ListView struct {
WindowBase
// OnItemActivate fires on item activation (double click / Enter), if available.
OnItemActivate func(index int)
// OnItemChanged fires on LVN_ITEMCHANGED.
OnItemChanged func(index int)
}
const lvmGetItemCount = win.LVM_FIRST + 4
func (lv *ListView) WndProc(msg uint32, wParam, lParam uintptr) uintptr {
switch msg {
case win.WM_NOTIFY:
nmhdr := (*win.NMHDR)(unsafe.Pointer(lParam))
code := uint32(nmhdr.Code)
switch code {
case win.LVN_ITEMCHANGED:
if lv.OnItemChanged != nil {
nmlv := (*win.NMLISTVIEW)(unsafe.Pointer(lParam))
lv.OnItemChanged(int(nmlv.IItem))
}
return 0
case win.NM_DBLCLK:
if lv.OnItemActivate != nil {
nmia := (*win.NMITEMACTIVATE)(unsafe.Pointer(lParam))
lv.OnItemActivate(int(nmia.IItem))
}
return 0
}
return 0
}
return lv.AsWindowBase().WndProc(msg, wParam, lParam)
}
// SetExtendedStyle sets extended list-view styles (e.g. LVS_EX_FULLROWSELECT).
func (lv *ListView) SetExtendedStyle(style uint32) {
lv.SendMessage(win.LVM_SETEXTENDEDLISTVIEWSTYLE, 0, uintptr(style))
}
// InsertColumn inserts a column at index and returns the actual inserted index (or -1).
func (lv *ListView) InsertColumn(index int, text string, width int, fmt int32) int {
utf16 := syscall.StringToUTF16(text)
col := win.LVCOLUMN{
Mask: win.LVCF_TEXT | win.LVCF_WIDTH | win.LVCF_FMT | win.LVCF_SUBITEM,
Fmt: fmt,
Cx: int32(width),
PszText: &utf16[0],
ISubItem: int32(index),
}
ret := lv.SendMessage(win.LVM_INSERTCOLUMN, uintptr(index), uintptr(unsafe.Pointer(&col)))
return int(int32(ret))
}
// InsertItem inserts a new item at index (or appends if index < 0) and returns its index (or -1).
func (lv *ListView) InsertItem(index int, text string) int {
if index < 0 {
index = lv.ItemCount()
}
utf16 := syscall.StringToUTF16(text)
item := win.LVITEM{
Mask: win.LVIF_TEXT,
IItem: int32(index),
ISubItem: 0,
PszText: &utf16[0],
}
ret := lv.SendMessage(win.LVM_INSERTITEM, 0, uintptr(unsafe.Pointer(&item)))
return int(int32(ret))
}
// SetItemText sets the text for an item/subitem.
func (lv *ListView) SetItemText(itemIndex int, subItem int, text string) bool {
utf16 := syscall.StringToUTF16(text)
item := win.LVITEM{
IItem: int32(itemIndex),
ISubItem: int32(subItem),
PszText: &utf16[0],
}
ret := lv.SendMessage(win.LVM_SETITEMTEXT, uintptr(itemIndex), uintptr(unsafe.Pointer(&item)))
return ret != 0
}
// GetItemText returns the text for an item/subitem.
func (lv *ListView) GetItemText(itemIndex int, subItem int) string {
buf := make([]uint16, 512)
item := win.LVITEM{
IItem: int32(itemIndex),
ISubItem: int32(subItem),
CchTextMax: int32(len(buf)),
PszText: &buf[0],
}
lv.SendMessage(win.LVM_GETITEMTEXT, uintptr(itemIndex), uintptr(unsafe.Pointer(&item)))
return syscall.UTF16ToString(buf)
}
// ItemCount returns the number of items in the list.
func (lv *ListView) ItemCount() int {
return int(int32(lv.SendMessage(lvmGetItemCount, 0, 0)))
}
// DeleteAllItems deletes all items.
func (lv *ListView) DeleteAllItems() bool {
return lv.SendMessage(win.LVM_DELETEALLITEMS, 0, 0) != 0
}
// DeleteItem deletes an item at index.
func (lv *ListView) DeleteItem(index int) bool {
return lv.SendMessage(win.LVM_DELETEITEM, uintptr(index), 0) != 0
}
// SelectedIndex returns the first selected item index, or -1 if none.
func (lv *ListView) SelectedIndex() int {
ret := lv.SendMessage(win.LVM_GETNEXTITEM, ^uintptr(0), uintptr(win.LVNI_SELECTED))
return int(int32(ret))
}
// NewListView creates a new ListView, need bind to Dialog before use.
func NewListView(idd uintptr) *ListView {
return &ListView{WindowBase: WindowBase{idd: idd}}
}
// BindNewListView creates a new ListView and bind to target dlg.
func BindNewListView(idd uintptr, dlg *Dialog) (*ListView, error) {
lv := NewListView(idd)
err := dlg.BindWidgets(lv)
return lv, err
}