예제 #1
0
        /// <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);
        }
예제 #2
0
 public static extern IntPtr PostMessage(IntPtr hWnd, APIsEnums.WindowMessages msg, int wParam, int lParam);