-
Notifications
You must be signed in to change notification settings - Fork 6
/
ListViewEx.cs
227 lines (186 loc) · 7.02 KB
/
ListViewEx.cs
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace csharp_File_Shredder
{
// ORIGINAL CREDIT TO - I MAY HAVE MODIFIED IT ?
/// <summary>
/// Zusammenfassung für ListViewEx.
/// </summary>
public class ListViewEx : ListView
{
#region Interop-Defines
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wPar, IntPtr lPar);
// ListView messages
private const int LVM_FIRST = 0x1000;
private const int LVM_GETCOLUMNORDERARRAY = (LVM_FIRST + 59);
#endregion
private struct EmbeddedControl : IEquatable<EmbeddedControl>
{
public Control Control;
public int Column;
public int Row;
public DockStyle Dock;
public ListViewItem Item;
public bool Equals(EmbeddedControl obj) => (obj is EmbeddedControl embededControl) && embededControl.Control == Control;
}
private ArrayList _embeddedControls = new ArrayList();
protected int[] GetColumnOrder()
{
IntPtr lPar = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)) * Columns.Count);
IntPtr res = SendMessage(Handle, LVM_GETCOLUMNORDERARRAY, new IntPtr(Columns.Count), lPar);
if (res.ToInt32() == 0) // Something went wrong
{
Marshal.FreeHGlobal(lPar);
return null;
}
int[] order = new int[Columns.Count];
Marshal.Copy(lPar, order, 0, Columns.Count);
Marshal.FreeHGlobal(lPar);
return order;
}
protected Rectangle GetSubItemBounds(ListViewItem Item, int SubItem)
{
Rectangle subItemRect = Rectangle.Empty;
if (Item == null) {
throw new ArgumentNullException("Item");
}
int[] order = GetColumnOrder();
if (order == null) {
return subItemRect;
}
if (SubItem >= order.Length) {
throw new ArgumentOutOfRangeException("SubItem " + SubItem + " out of range");
}
// Retrieve the bounds of the entire ListViewItem (all subitems)
Rectangle lviBounds = Item.GetBounds(ItemBoundsPortion.Entire);
int subItemX = lviBounds.Left;
// Calculate the X position of the SubItem.
// Because the columns can be reordered we have to use Columns[order[i]] instead of Columns[i] !
ColumnHeader col;
int i;
for (i = 0; i < order.Length; i++) {
col = this.Columns[order[i]];
if (col.Index == SubItem) {
break;
}
subItemX += col.Width;
}
subItemRect = new Rectangle(subItemX, lviBounds.Top, this.Columns[order[i]].Width, lviBounds.Height);
return subItemRect;
}
public void AddEmbeddedControl(Control c, int col, int row)
{
AddEmbeddedControl(c, col, row, DockStyle.Fill);
}
public void AddEmbeddedControl(Control c, int col, int row, DockStyle dock)
{
if (c == null) {
throw new ArgumentNullException();
}
if (col >= Columns.Count || row >= Items.Count) {
throw new ArgumentOutOfRangeException();
}
EmbeddedControl ec;
ec.Control = c;
ec.Column = col;
ec.Row = row;
ec.Dock = dock;
ec.Item = Items[row];
_embeddedControls.Add(ec);
this.Controls.Add(c);
}
public void RemoveFirst()
{
RemoveItem(0);
}
public void RemoveItem(int index)
{
EmbeddedControl ec = (EmbeddedControl)_embeddedControls[index];
if (ec.Control == null || ec.Item == null) {
throw new ArgumentNullException();
}
this.Controls.Remove(ec.Control);
_embeddedControls.Remove((object)ec);
ec.Item.Remove();
}
public void RemoveAllControls()
{
foreach (EmbeddedControl ec in _embeddedControls) {
this.Controls.Remove(ec.Control);
ec.Item.Remove();
}
_embeddedControls.RemoveRange(0, _embeddedControls.Count);
}
public Control GetEmbeddedControl(int col, int row)
{
foreach (EmbeddedControl ec in _embeddedControls) {
if (ec.Row == row && ec.Column == col) {
return ec.Control;
}
}
return null;
}
[DefaultValue(View.LargeIcon)]
public new View View
{
get {
return base.View;
}
set {
// Embedded controls are rendered only when we're in Details mode
foreach (EmbeddedControl ec in _embeddedControls) {
ec.Control.Visible = (value == View.Details);
}
base.View = value;
}
}
protected override void WndProc(ref Message m)
{
const int WM_PAINT = 0x000F;
if (m.Msg == WM_PAINT) {
if (View != View.Details) {
return;
}
// Calculate the position of all embedded controls
foreach (EmbeddedControl ec in _embeddedControls) {
Rectangle rc = this.GetSubItemBounds(ec.Item, ec.Column);
if ((this.HeaderStyle != ColumnHeaderStyle.None) &&
(rc.Top < this.Font.Height)) // Control overlaps ColumnHeader
{
ec.Control.Visible = false;
continue;
} else {
ec.Control.Visible = true;
}
switch (ec.Dock) {
case DockStyle.Top:
rc.Height = ec.Control.Height;
break;
case DockStyle.Left:
rc.Width = ec.Control.Width;
break;
case DockStyle.Bottom:
rc.Offset(0, rc.Height - ec.Control.Height);
rc.Height = ec.Control.Height;
break;
case DockStyle.Right:
rc.Offset(rc.Width - ec.Control.Width, 0);
rc.Width = ec.Control.Width;
break;
case DockStyle.None:
rc.Size = ec.Control.Size;
break;
}
// Set embedded control's bounds
ec.Control.Bounds = rc;
}
}
base.WndProc(ref m);
}
}
}