Skip to content

Commit 0e65a88

Browse files
author
grammarian
committed
Hardened code against the rare case of the control having no columns (SF bug #174)
git-svn-id: https://svn.code.sf.net/p/objectlistview/code/cs/trunk@833 0bec5ed8-b53f-49e6-9885-ce7bc93af311
1 parent 62bd8f8 commit 0e65a88

File tree

2 files changed

+47
-10
lines changed

2 files changed

+47
-10
lines changed

ObjectListView/Implementation/OLVListItem.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* Date: 31-March-2011 5:53 pm
66
*
77
* Change log:
8+
* 2018-09-01 JPP - Handle rare case of getting subitems when there are no columns
9+
* v2.9
810
* 2015-08-22 JPP - Added OLVListItem.SelectedBackColor and SelectedForeColor
911
* 2015-06-09 JPP - Added HasAnyHyperlinks property
1012
* v2.8
@@ -13,7 +15,7 @@
1315
* vOld
1416
* 2011-03-31 JPP - Split into its own file
1517
*
16-
* Copyright (C) 2011-2015 Phillip Piper
18+
* Copyright (C) 2011-2018 Phillip Piper
1719
*
1820
* This program is free software: you can redistribute it and/or modify
1921
* it under the terms of the GNU General Public License as published by
@@ -293,7 +295,9 @@ public Color? SelectedForeColor
293295
/// <returns>An OLVListSubItem</returns>
294296
public virtual OLVListSubItem GetSubItem(int index) {
295297
if (index >= 0 && index < this.SubItems.Count)
296-
return (OLVListSubItem)this.SubItems[index];
298+
// If the control has 0 columns, ListViewItem.SubItems will auto create a
299+
// SubItem of the wrong type. Casting using 'as' handles this rare case.
300+
return this.SubItems[index] as OLVListSubItem;
297301

298302
return null;
299303
}

ObjectListView/ObjectListView.cs

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* Date: 9/10/2006 11:15 AM
66
*
77
* Change log
8+
* 2018-09-01 JPP - Hardened code against the rare case of the control having no columns (SF bug #174)
9+
* The underlying ListView does not like having rows when there are no columns and throws exceptions.j
810
* 2018-05-05 JPP - Added OLVColumn.EditorCreator to allow fine control over what control is used to edit
911
* a particular cell.
1012
* - Added IOlvEditor to allow custom editor to easily integrate with our editing scheme
@@ -4812,6 +4814,10 @@ protected OlvListViewHitTestInfo LowLevelHitTest(int x, int y) {
48124814
if (!this.ClientRectangle.Contains(x, y))
48134815
return new OlvListViewHitTestInfo(null, null, 0, null, 0);
48144816

4817+
// If there are no columns, also don't bother with anything else
4818+
if (this.Columns.Count == 0)
4819+
return new OlvListViewHitTestInfo(null, null, 0, null, 0);
4820+
48154821
// Is the point over the header?
48164822
OlvListViewHitTestInfo.HeaderHitTestInfo headerHitTestInfo = this.HeaderControl.HitTest(x, y);
48174823
if (headerHitTestInfo != null)
@@ -6157,6 +6163,8 @@ protected virtual bool HandleFindItem(ref Message m) {
61576163
/// search the every row until a match is found, wrapping at the end if needed.</remarks>
61586164
public virtual int FindMatchingRow(string text, int start, SearchDirectionHint direction) {
61596165
// We also can't do anything if we don't have data
6166+
if (this.Columns.Count == 0)
6167+
return -1;
61606168
int rowCount = this.GetItemCount();
61616169
if (rowCount == 0)
61626170
return -1;
@@ -6327,6 +6335,10 @@ public void ToggleSelectedRowCheckBoxes() {
63276335
/// <param name="m">The m to be processed</param>
63286336
/// <returns>bool to indicate if the msg has been handled</returns>
63296337
protected virtual bool HandleLButtonDown(ref Message m) {
6338+
// If there are no columns, the base ListView class can throw OutOfRange exceptions.
6339+
if (this.Columns.Count == 0)
6340+
return true;
6341+
63306342
// We have to intercept this low level message rather than the more natural
63316343
// overridding of OnMouseDown, since ListCtrl's internal mouse down behavior
63326344
// is to select (or deselect) rows when the mouse is released. We don't
@@ -6395,6 +6407,10 @@ protected virtual bool ProcessLButtonDown(OlvListViewHitTestInfo hti) {
63956407
/// <param name="m">The m to be processed</param>
63966408
/// <returns>bool to indicate if the msg has been handled</returns>
63976409
protected virtual bool HandleLButtonUp(ref Message m) {
6410+
// If there are no columns, the base ListView class can throw OutOfRange exceptions.
6411+
if (this.Columns.Count == 0)
6412+
return true;
6413+
63986414
if (this.MouseMoveHitTest == null)
63996415
return false;
64006416

@@ -6446,6 +6462,10 @@ protected virtual bool TriggerGroupExpandCollapse(OLVGroup group)
64466462
/// <param name="m">The m to be processed</param>
64476463
/// <returns>bool to indicate if the msg has been handled</returns>
64486464
protected virtual bool HandleRButtonDown(ref Message m) {
6465+
// If there are no columns, the base ListView class can throw OutOfRange exceptions.
6466+
if (this.Columns.Count == 0)
6467+
return true;
6468+
64496469
int x = m.LParam.ToInt32() & 0xFFFF;
64506470
int y = (m.LParam.ToInt32() >> 16) & 0xFFFF;
64516471

@@ -6458,7 +6478,7 @@ protected virtual bool HandleRButtonDown(ref Message m) {
64586478
/// <remarks>Subclasses can override this to do something unique</remarks>
64596479
/// <param name="hti"></param>
64606480
/// <returns>True if the message has been handled</returns>
6461-
protected virtual bool ProcessRButtonDown(OlvListViewHitTestInfo hti) {
6481+
protected virtual bool ProcessRButtonDown(OlvListViewHitTestInfo hti) {
64626482
if (hti.Item == null)
64636483
return false;
64646484

@@ -6472,6 +6492,10 @@ protected virtual bool ProcessRButtonDown(OlvListViewHitTestInfo hti) {
64726492
/// <param name="m">The m to be processed</param>
64736493
/// <returns>bool to indicate if the msg has been handled</returns>
64746494
protected virtual bool HandleLButtonDoubleClick(ref Message m) {
6495+
// If there are no columns, the base ListView class can throw OutOfRange exceptions.
6496+
if (this.Columns.Count == 0)
6497+
return true;
6498+
64756499
int x = m.LParam.ToInt32() & 0xFFFF;
64766500
int y = (m.LParam.ToInt32() >> 16) & 0xFFFF;
64776501

@@ -6485,7 +6509,6 @@ protected virtual bool HandleLButtonDoubleClick(ref Message m) {
64856509
/// <param name="hti"></param>
64866510
/// <returns>True if the message has been handled</returns>
64876511
protected virtual bool ProcessLButtonDoubleClick(OlvListViewHitTestInfo hti) {
6488-
64896512
// If the user double clicked on a checkbox, ignore it
64906513
return (hti.HitTestLocation == HitTestLocation.CheckBox);
64916514
}
@@ -6496,6 +6519,11 @@ protected virtual bool ProcessLButtonDoubleClick(OlvListViewHitTestInfo hti) {
64966519
/// <param name="m">The m to be processed</param>
64976520
/// <returns>bool to indicate if the msg has been handled</returns>
64986521
protected virtual bool HandleRButtonDoubleClick(ref Message m) {
6522+
6523+
// If there are no columns, the base ListView class can throw OutOfRange exceptions.
6524+
if (this.Columns.Count == 0)
6525+
return true;
6526+
64996527
int x = m.LParam.ToInt32() & 0xFFFF;
65006528
int y = (m.LParam.ToInt32() >> 16) & 0xFFFF;
65016529

@@ -6602,7 +6630,7 @@ protected virtual bool HandleReflectNotify(ref Message m) {
66026630
//System.Diagnostics.Debug.WriteLine("LVN_GETINFOTIP");
66036631
// When virtual lists are in SmallIcon view, they generates tooltip message with invalid item indices.
66046632
NativeMethods.NMLVGETINFOTIP nmGetInfoTip = (NativeMethods.NMLVGETINFOTIP)m.GetLParam(typeof(NativeMethods.NMLVGETINFOTIP));
6605-
isMsgHandled = nmGetInfoTip.iItem >= this.GetItemCount();
6633+
isMsgHandled = nmGetInfoTip.iItem >= this.GetItemCount() || this.Columns.Count == 0;
66066634
break;
66076635

66086636
case NM_RELEASEDCAPTURE:
@@ -7804,9 +7832,9 @@ public virtual void UncheckSubItem(object rowObject, OLVColumn column)
78047832
/// Return the column at the given index
78057833
/// </summary>
78067834
/// <param name="index">Index of the column to be returned</param>
7807-
/// <returns>An OLVColumn</returns>
7835+
/// <returns>An OLVColumn, or null if the index is out of bounds</returns>
78087836
public virtual OLVColumn GetColumn(int index) {
7809-
return (OLVColumn)this.Columns[index];
7837+
return (index >=0 && index < this.Columns.Count) ? (OLVColumn)this.Columns[index] : null;
78107838
}
78117839

78127840
/// <summary>
@@ -8714,6 +8742,8 @@ protected virtual void PostProcessRows() {
87148742
/// Do the work required after one item in a listview have been created
87158743
/// </summary>
87168744
protected virtual void PostProcessOneRow(int rowIndex, int displayIndex, OLVListItem olvi) {
8745+
if (this.Columns.Count == 0)
8746+
return;
87178747
if (this.UseAlternatingBackColors && this.View == View.Details && olvi.Enabled) {
87188748
olvi.UseItemStyleForSubItems = true;
87198749
olvi.BackColor = displayIndex % 2 == 1 ? this.AlternateRowBackColorOrDefault : this.BackColor;
@@ -8882,7 +8912,7 @@ private static void PropagateFormatFromRowToCells(OLVListItem olvi) {
88828912
Color backColor = olvi.BackColor;
88838913
Color foreColor = olvi.ForeColor;
88848914
Font font = olvi.Font;
8885-
foreach (OLVListSubItem subitem in olvi.SubItems) {
8915+
foreach (ListViewItem.ListViewSubItem subitem in olvi.SubItems) {
88868916
subitem.BackColor = backColor;
88878917
subitem.ForeColor = foreColor;
88888918
subitem.Font = font;
@@ -9536,7 +9566,8 @@ public virtual void EditModel(object rowModel) {
95369566
return;
95379567

95389568
for (int i = 0; i < olvItem.SubItems.Count; i++) {
9539-
if (this.GetColumn(i).IsEditable) {
9569+
var olvColumn = this.GetColumn(i);
9570+
if (olvColumn != null && olvColumn.IsEditable) {
95409571
this.StartCellEdit(olvItem, i);
95419572
return;
95429573
}
@@ -9573,6 +9604,8 @@ public virtual void EditSubItem(OLVListItem item, int subItemIndex) {
95739604
/// <param name="subItemIndex">The index of the cell to be edited</param>
95749605
public virtual void StartCellEdit(OLVListItem item, int subItemIndex) {
95759606
OLVColumn column = this.GetColumn(subItemIndex);
9607+
if (column == null)
9608+
return;
95769609
Control c = this.GetCellEditor(item, subItemIndex);
95779610
Rectangle cellBounds = this.CalculateCellBounds(item, subItemIndex);
95789611
c.Bounds = this.CalculateCellEditorBounds(item, subItemIndex, c.PreferredSize);
@@ -10258,7 +10291,7 @@ protected virtual void UpdateHotRow(int rowIndex, int columnIndex, HitTestLocati
1025810291
if (this.UseHyperlinks) {
1025910292
OLVColumn column = this.GetColumn(columnIndex);
1026010293
OLVListSubItem subItem = olvi.GetSubItem(columnIndex);
10261-
if (column.Hyperlink && hitLocation == HitTestLocation.Text && !String.IsNullOrEmpty(subItem.Url)) {
10294+
if (column != null && column.Hyperlink && hitLocation == HitTestLocation.Text && !String.IsNullOrEmpty(subItem.Url)) {
1026210295
this.ApplyCellStyle(olvi, columnIndex, this.HyperlinkStyle.Over);
1026310296
this.Cursor = this.HyperlinkStyle.OverCursor ?? Cursors.Default;
1026410297
} else {

0 commit comments

Comments
 (0)