/// <summary> /// WndProc /// </summary> /// <param name="m"></param> protected override void WndProc(ref System.Windows.Forms.Message m) { //stop messages which dont go away after X seconds if (lastmsg != (APIsEnums.WindowMessages)m.Msg) { lastmsg = (APIsEnums.WindowMessages)m.Msg; starttime = System.DateTime.Now; } else { DateTime now = System.DateTime.Now; TimeSpan TS = now.Subtract(starttime); if (TS.TotalSeconds>5) return; } TreeListViewItem item = null; Rectangle rec; switch ((APIsEnums.WindowMessages)m.Msg) { #region NOTIFY case APIsEnums.WindowMessages.NOTIFY: case (APIsEnums.WindowMessages)APIsEnums.ReflectedMessages.NOTIFY: APIsStructs.NMHDR nmhdr = (APIsStructs.NMHDR)m.GetLParam(typeof(APIsStructs.NMHDR)); APIsStructs.NMHEADER nmheader = (APIsStructs.NMHEADER)m.GetLParam(typeof(APIsStructs.NMHEADER)); switch ((APIsEnums.ListViewNotifications)nmhdr.code) { #region APIsEnums.ListViewNotifications.MARQUEEBEGIN case APIsEnums.ListViewNotifications.MARQUEEBEGIN: if ((MouseButtons & MouseButtons.Left) != MouseButtons.Left) m.Result = (IntPtr)1; else _hasMarquee = true; break; #endregion #region APIsEnums.ListViewNotifications.ITEMCHANGING case APIsEnums.ListViewNotifications.ITEMCHANGING: APIsStructs.NMLISTVIEW nmlistview = (APIsStructs.NMLISTVIEW)m.GetLParam(typeof(APIsStructs.NMLISTVIEW)); if (nmlistview.iItem < 0) break; if ((item = GetTreeListViewItemFromIndex(nmlistview.iItem)) == null) break; bool cancel = false; if (nmlistview.Select) { if (_selectionMark == null) _selectionMark = item; else if (!_selectionMark.Visible) _selectionMark = item; if (HasMarquee) item.Focused = true; } else if (nmlistview.UnSelect && HasMarquee) { if (item.NextVisibleItem != null) if (item.NextVisibleItem.Selected) item.NextVisibleItem.Focused = true; if (item.PrevVisibleItem != null) if (item.PrevVisibleItem.Selected) item.PrevVisibleItem.Focused = true; } #region Select after dbl click // Disable the selection after a double click (normaly, if the control scrolls after // a collapse, the new item under the cursor is automatically selected...) if (_dblclicktime.AddMilliseconds(500).CompareTo(DateTime.Now) > 0 && (nmlistview.Select || nmlistview.Focus) && FocusedItem != item) cancel = true; #endregion #region Wrong Level Select if (((APIsEnums.ListViewItemStates)nmlistview.uNewState & APIsEnums.ListViewItemStates.SELECTED) == APIsEnums.ListViewItemStates.SELECTED && MultiSelect) if (SelectedIndices.Count > 0) if (GetTreeListViewItemFromIndex(nmlistview.iItem).Parent != SelectedItems[0].Parent) cancel = true; #endregion #region Check during selection // Disable check boxes check when : // - the Marquee selection tool is being used // - the Ctrl or Shift keys are down bool state = (nmlistview.uChanged & (uint)APIsEnums.ListViewItemFlags.STATE) == (uint)APIsEnums.ListViewItemFlags.STATE; bool ctrlKeyDown = (ModifierKeys & Keys.Control) == Keys.Control; bool shiftKeyDown = (ModifierKeys & Keys.Shift) == Keys.Shift; if ((nmlistview.Check || nmlistview.UnCheck) && (HasMarquee || ctrlKeyDown || shiftKeyDown)) { // MessageBox.Show(this, // "uChanged = " + nmlistview->uChanged.ToString() + "\n\n" + // "uOld = " + nmlistview->uOldState.ToString() + "\n" + // "uNew = " + nmlistview->uChanged.ToString() + "\n\n" + // "OldCheck : " + (oldCheck ? "true" : "false") + "\n" + // "NewCheck : " + (newCheck ? "true" : "false")); cancel = true; } #endregion if (cancel) { m.Result = (IntPtr)1; return; } break; #endregion #region APIsEnums.ListViewNotifications.BEGINLABELEDIT case APIsEnums.ListViewNotifications.BEGINLABELEDIT: // Cancel label edit if the message is sent just after a double click if (_lastdoubleclick.AddMilliseconds(450) > DateTime.Now) { Message canceledit = Message.Create(Handle, (int)APIsEnums.ListViewMessages.CANCELEDITLABEL, IntPtr.Zero, IntPtr.Zero); WndProc(ref canceledit); m.Result = (IntPtr)1; return; } item = _lastitemclicked.Item; item.EnsureVisible(); // Add subitems if needed while (item.SubItems.Count - 1 < _lastitemclicked.ColumnIndex) item.SubItems.Add(""); TreeListViewBeforeLabelEditEventArgs beforeed = new TreeListViewBeforeLabelEditEventArgs( FocusedItem, _lastitemclicked.ColumnIndex, item.SubItems[_lastitemclicked.ColumnIndex].Text); OnBeforeLabelEdit(beforeed); if (beforeed.Cancel) { Message canceledit = Message.Create(Handle, (int)APIsEnums.ListViewMessages.CANCELEDITLABEL, IntPtr.Zero, IntPtr.Zero); WndProc(ref canceledit); m.Result = (IntPtr)1; return; } _inedit = true; // Get edit handle Message mess = Message.Create(Handle, (int)APIsEnums.ListViewMessages.GETEDITCONTROL, IntPtr.Zero, IntPtr.Zero); WndProc(ref mess); IntPtr edithandle = mess.Result; _customedit = new CustomEdit(edithandle, this, beforeed.Editor); _editeditem = new EditItemInformations( FocusedItem, beforeed.ColumnIndex, FocusedItem.SubItems[beforeed.ColumnIndex].Text); m.Result = IntPtr.Zero; return; #endregion #region APIsEnums.ListViewNotifications.ENDLABELEDIT case APIsEnums.ListViewNotifications.ENDLABELEDIT: if (_customedit != null) _customedit.HideEditControl(); _customedit = null; _inedit = false; _editeditem = new EditItemInformations(); m.Result = IntPtr.Zero; return; #endregion #region CUSTOMDRAW case (APIsEnums.ListViewNotifications)APIsEnums.NotificationMessages.CUSTOMDRAW: base.WndProc(ref m); CustomDraw(ref m); return; #endregion #region BEGINSCROLL case APIsEnums.ListViewNotifications.BEGINSCROLL: _updating = true; break; #endregion #region ENDSCROLL case APIsEnums.ListViewNotifications.ENDSCROLL: _updating = false; // Disable display bug with vertical lines (slow...) // if(ShowPlusMinus) // { // DrawPlusMinusItemsLines(); // DrawPlusMinusItems(); // } break; #endregion #region APIsEnums.HeaderControlNotifications.BEGINDRAG case (APIsEnums.ListViewNotifications)APIsEnums.HeaderControlNotifications.BEGINDRAG: nmheader = (APIsStructs.NMHEADER)m.GetLParam(typeof(APIsStructs.NMHEADER)); if (nmheader.iItem == 0) { m.Result = (IntPtr)1; return; } break; #endregion #region APIsEnums.HeaderControlNotifications.ENDDRAG case (APIsEnums.ListViewNotifications)APIsEnums.HeaderControlNotifications.ENDDRAG: nmheader = (APIsStructs.NMHEADER)m.GetLParam(typeof(APIsStructs.NMHEADER)); // Get mouse position in header coordinates IntPtr headerHandle = (IntPtr)APIsUser32.SendMessage(Handle, (int)APIsEnums.ListViewMessages.GETHEADER, IntPtr.Zero, IntPtr.Zero); APIsStructs.POINTAPI pointapi = new APIsStructs.POINTAPI(MousePosition); APIsUser32.ScreenToClient(headerHandle, ref pointapi); // HeaderItem Rect APIsStructs.RECT headerItemRect = new APIsStructs.RECT(); APIsUser32.SendMessage(headerHandle, (int)APIsEnums.HeaderControlMessages.GETITEMRECT, 0, ref headerItemRect); int headerItemWidth = headerItemRect.right - headerItemRect.left; // Cancel the drag operation if the first column is moved // or destination is the first column if (pointapi.x <= headerItemRect.left + headerItemWidth / 2 || nmheader.iItem == 0) { m.Result = (IntPtr)1; return; } break; #endregion #region APIsEnums.HeaderControlNotifications.TRACK / ENDTRACK // case (APIsEnums.ListViewNotifications)APIsEnums.HeaderControlNotifications.TRACK: case (APIsEnums.ListViewNotifications)APIsEnums.HeaderControlNotifications.ENDTRACK: Invalidate(); break; #endregion } break; #endregion #region LBUTTONDOWN // Cancel the click on checkboxes if the item is not "checkable" case APIsEnums.WindowMessages.LBUTTONDOWN: if (Columns.Count == 0) break; // Set the clickeditem and column int colclicked = GetColumnAt(MousePosition); if (colclicked == -1) colclicked = 0; item = GetItemAtFullRow(PointToClient(MousePosition)); _lastitemclicked = new EditItemInformations(item, colclicked, ""); if (_selectionMark == null || !_selectionMark.Visible) _selectionMark = item; try { if (((APIsEnums.KeyStatesMasks)(int)m.WParam & APIsEnums.KeyStatesMasks.SHIFT) != APIsEnums.KeyStatesMasks.SHIFT && !(((APIsEnums.KeyStatesMasks)(int)m.WParam & APIsEnums.KeyStatesMasks.CONTROL) == APIsEnums.KeyStatesMasks.CONTROL && item.Parent != _selectionMark.Parent)) _selectionMark = item; } catch (Exception) { } // Get where the mouse has clicked APIsStructs.LVHITTESTINFO lvhittest = new APIsStructs.LVHITTESTINFO(); lvhittest.pt = new APIsStructs.POINTAPI(PointToClient(MousePosition)); APIsUser32.SendMessage(Handle, (Int32)APIsEnums.ListViewMessages.HITTEST, 0, ref lvhittest); if (item == null) break; // Plus / Minus click if (item.GetBounds(TreeListViewItemBoundsPortion.PlusMinus).Contains(PointToClient(MousePosition)) && ShowPlusMinus && item.Items.Count > 0 && Columns[0].Width > (item.Level + 1) * SystemInformation.SmallIconSize.Width) { Focus(); if (item.IsExpanded) item.Collapse(); else item.Expand(); OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, PointToClient(MousePosition).X, PointToClient(MousePosition).Y, 0)); return; } // Cancel mouse click if multiselection on a wrong item if (SelectedIndices.Count > 0 && (((APIsEnums.KeyStatesMasks)(int)m.WParam & APIsEnums.KeyStatesMasks.SHIFT) == APIsEnums.KeyStatesMasks.SHIFT || ((APIsEnums.KeyStatesMasks)(int)m.WParam & APIsEnums.KeyStatesMasks.CONTROL) == APIsEnums.KeyStatesMasks.CONTROL) && MultiSelect) { if (_selectionMark.Parent == item.Parent && ((APIsEnums.KeyStatesMasks)(int)m.WParam & APIsEnums.KeyStatesMasks.SHIFT) == APIsEnums.KeyStatesMasks.SHIFT) { _updating = true; SetSelectedItemsRange(item, _selectionMark); // Prevent all item at the wrong level of being selected m.WParam = (IntPtr)APIsEnums.KeyStatesMasks.CONTROL; base.WndProc(ref m); item.Selected = true; _updating = false; DrawSelectedItemsFocusCues(); return; } } break; #endregion #region LBUTTONDBLCLK // Disable this notification to remove the auto-check when // the user double-click on an item and append the expand / collapse function case APIsEnums.WindowMessages.LBUTTONDBLCLK: _lastdoubleclick = DateTime.Now; if (FocusedItem != null) { item = FocusedItem; bool doExpColl = false; switch (ExpandMethod) { case TreeListViewExpandMethod.IconDbleClick: rec = item.GetBounds(ItemBoundsPortion.Icon); if (rec.Contains(PointToClient(MousePosition))) doExpColl = true; break; case TreeListViewExpandMethod.ItemOnlyDbleClick: rec = item.GetBounds(ItemBoundsPortion.ItemOnly); if (rec.Contains(PointToClient(MousePosition))) doExpColl = true; break; case TreeListViewExpandMethod.EntireItemDbleClick: rec = item.GetBounds(ItemBoundsPortion.Entire); if (rec.Contains(PointToClient(MousePosition))) doExpColl = true; break; default: break; } if (doExpColl) { _dblclicktime = DateTime.Now; Cursor = Cursors.WaitCursor; BeginUpdate(); if (item.IsExpanded) item.Collapse(); else item.Expand(); EndUpdate(); Cursor = Cursors.Default; } } OnDoubleClick(new EventArgs()); return; #endregion #region MOUSEMOVE case APIsEnums.WindowMessages.MOUSEMOVE: if ((MouseButtons & MouseButtons.Left) != MouseButtons.Left && HasMarquee) _hasMarquee = false; break; #endregion #region UNICHAR, CHAR, KEYDOWN case APIsEnums.WindowMessages.UNICHAR: case APIsEnums.WindowMessages.CHAR: CharPressed((char)m.WParam); return; case APIsEnums.WindowMessages.KEYDOWN: OnKeyDown(new KeyEventArgs((Keys)(int)m.WParam)); return; #endregion #region PAINT case APIsEnums.WindowMessages.PAINT: if (InEdit && EditedItem.Item != null) { APIsStructs.RECT rect = new APIsStructs.RECT( EditedItem.Item.GetBounds(ItemBoundsPortion.Entire)); APIsUser32.ValidateRect(Handle, ref rect); } base.WndProc(ref m); DrawIntermediateStateItems(); DrawSelectedItemsFocusCues(); return; #endregion #region VSCROLL, HSCROLL, ENSUREVISIBLE case APIsEnums.WindowMessages.VSCROLL: case APIsEnums.WindowMessages.HSCROLL: case (APIsEnums.WindowMessages)APIsEnums.ListViewMessages.ENSUREVISIBLE: if (!Scrollable) { m.Result = (IntPtr)0; return; } break; #endregion } base.WndProc(ref m); }
public static extern IntPtr PostMessage(IntPtr hWnd, APIsEnums.WindowMessages msg, int wParam, int lParam);