protected virtual bool HandleChar(ref Message m)
{
// Trigger a normal KeyPress event, which listeners can handle if they want.
// Handling the event stops ObjectListView's fancy search-by-typing.
if (this.ProcessKeyEventArgs(ref m))
return true;
const int MILLISECONDS_BETWEEN_KEYPRESSES = 1000;
// What character did the user type and was it part of a longer string?
char character = (char)m.WParam.ToInt32(); //TODO: Will this work on 64 bit or MBCS?
if (character == (char)Keys.Back) {
// Backspace forces the next key to be considered the start of a new search
this.timeLastCharEvent = 0;
return true;
}
if (System.Environment.TickCount < (this.timeLastCharEvent + MILLISECONDS_BETWEEN_KEYPRESSES))
this.lastSearchString += character;
else
this.lastSearchString = character.ToString(CultureInfo.InvariantCulture);
// If this control is showing checkboxes, we want to ignore single space presses,
// since they are used to toggle the selected checkboxes.
if (this.CheckBoxes && this.lastSearchString == " ") {
this.timeLastCharEvent = 0;
return true;
}
// Where should the search start?
int start = 0;
ListViewItem focused = this.FocusedItem;
if (focused != null) {
start = this.GetDisplayOrderOfItemIndex(focused.Index);
// If the user presses a single key, we search from after the focused item,
// being careful not to march past the end of the list
if (this.lastSearchString.Length == 1) {
start += 1;
if (start == this.GetItemCount())
start = 0;
}
}
// Give the world a chance to fiddle with or completely avoid the searching process
BeforeSearchingEventArgs args = new BeforeSearchingEventArgs(this.lastSearchString, start);
this.OnBeforeSearching(args);
if (args.Canceled)
return true;
// The parameters of the search may have been changed
string searchString = args.StringToFind;
start = args.StartSearchFrom;
// Do the actual search
int found = this.FindMatchingRow(searchString, start, SearchDirectionHint.Down);
if (found >= 0) {
// Select and focus on the found item
this.BeginUpdate();
try {
this.SelectedIndices.Clear();
ListViewItem lvi = this.GetNthItemInDisplayOrder(found);
lvi.Selected = true;
lvi.Focused = true;
this.EnsureVisible(lvi.Index);
} finally {
this.EndUpdate();
}
}
// Tell the world that a search has occurred
AfterSearchingEventArgs args2 = new AfterSearchingEventArgs(searchString, found);
this.OnAfterSearching(args2);
if (!args2.Handled) {
if (found < 0)
System.Media.SystemSounds.Beep.Play();
}
// When did this event occur?
this.timeLastCharEvent = System.Environment.TickCount;
return true;
}