internal override void OnPropertyClicked(PropertyEnumerator enumSelf, Point point, Rectangle itemRect) { if ((ParentGrid.Enabled == false) && (ParentGrid.DisableMode != PropertyGrid.DisableModes.None)) return; Rectangle labelRect = GetLabelTextRect(itemRect, enumSelf); if (labelRect.Contains(point)) { PropertyHyperLinkClickedEventArgs ev = new PropertyHyperLinkClickedEventArgs(enumSelf, HyperLink); ParentGrid.OnHyperLinkPropertyClicked(ev); } }
internal override void OnPropertyClicked(PropertyEnumerator enumSelf, Point point, Rectangle itemRect) { if ((ParentGrid.Enabled == false) && (ParentGrid.DisableMode != PropertyGrid.DisableModes.None)) { return; } Rectangle labelRect = GetLabelTextRect(itemRect, enumSelf); if (labelRect.Contains(point)) { PropertyHyperLinkClickedEventArgs ev = new PropertyHyperLinkClickedEventArgs(enumSelf, HyperLink); ParentGrid.OnHyperLinkPropertyClicked(ev); } }
protected override void OnKeyDown(KeyEventArgs e) { // If only Control is clicked we simulate a mouse move so that the cursor could be updated on // a hyperlink property. if (e.KeyCode == Keys.ControlKey) { if (_currentInPlaceControl != null) { Win32Calls.RECT rect = new Win32Calls.RECT(); Win32Calls.GetWindowRect(_currentInPlaceControl.Handle, ref rect); Rectangle bounds = Rectangle.FromLTRB(rect.Left, rect.Top, rect.Right, rect.Bottom); if (bounds.Contains(MousePosition)) { base.OnKeyDown(e); return; } } Rectangle itemRect; Point pt = PointToClient(MousePosition); PropertyEnumerator propEnum = PropertyItemFromPoint(pt, out itemRect); if (propEnum.Property != null) propEnum.Property.OverrideCursor(pt, itemRect, propEnum); base.OnKeyDown(e); return; } Property selectedProperty = _selectedPropertyEnum.Property; if (selectedProperty != null) { // Hide the tooltip if it is visible // if (ToolTip != null) // ToolTip.SetText("", null); if (_currentInPlaceControl != null) { IInPlaceControl c = (_currentInPlaceControl as IInPlaceControl); if ((c != null) && c.OnParentKeyDown(e)) return; } switch (e.KeyCode) { case Keys.F4: { if ((_currentInPlaceControl != null) && (e.Modifiers == 0)) { IInPlaceControl c = (_currentInPlaceControl as IInPlaceControl); if (c != null) { c.OnF4(); } } break; } case Keys.Space: case Keys.Return: { if ((SelectedPropertyEnumerator.Property.CanBeDisabledManually) && (e.KeyCode == Keys.Space)) { if (SelectedPropertyEnumerator.HasParent == false) { EnableProperty(SelectedPropertyEnumerator, !SelectedPropertyEnumerator.Property.Enabled); #if _DOTNET2 e.SuppressKeyPress = true; #else HandleRef handle = new HandleRef(this, this.Handle); Win32Calls.RemovePendingMessages(handle, 0x102, 0x102); Win32Calls.RemovePendingMessages(handle, 0x106, 0x106); Win32Calls.RemovePendingMessages(handle, 0x286, 0x286); e.Handled = true; #endif } else { // The user can press on the checkbox only if its parent category is enabled if (SelectedPropertyEnumerator.Parent.Property.Enabled) { EnableProperty(SelectedPropertyEnumerator, !SelectedPropertyEnumerator.Property.Enabled); #if _DOTNET2 e.SuppressKeyPress = true; #else HandleRef handle = new HandleRef(this, this.Handle); Win32Calls.RemovePendingMessages(handle, 0x102, 0x102); Win32Calls.RemovePendingMessages(handle, 0x106, 0x106); Win32Calls.RemovePendingMessages(handle, 0x286, 0x286); e.Handled = true; #endif } } } // TODO : the following code should not be in this class. else if (SelectedPropertyEnumerator.Property is PropertyHyperLink) { if (SelectedPropertyEnumerator.Property.Enabled) { PropertyHyperLinkClickedEventArgs ev = new PropertyHyperLinkClickedEventArgs(SelectedPropertyEnumerator, SelectedPropertyEnumerator.Property.HyperLink); _parentCtrl.OnHyperLinkPropertyClicked(ev); } } else if (HasOneVisibleChild(SelectedPropertyEnumerator)) { Property property = SelectedPropertyEnumerator.Property; ExpandProperty(SelectedPropertyEnumerator, !property.Expanded); } break; } case Keys.Right: // Opens the item if it is a closed category case Keys.Add: { if ((e.KeyCode == Keys.Right) && (ModifierKeys == Keys.Control)) { SetLabelColumnWidthRatio((double)(LabelColumnWidth + 3) / (ClientRectangle.Width - LeftColumnWidth)); break; } if (SelectedPropertyEnumerator.Children.Count > 0) { Property property = SelectedPropertyEnumerator.Property; if (!property.Expanded && HasOneVisibleChild(SelectedPropertyEnumerator)) { ExpandProperty(SelectedPropertyEnumerator, true); break; } } if (e.KeyCode == Keys.Add) break; goto case Keys.Down; } case Keys.Down: // Moves the selected item down { if (e.Modifiers == Keys.Alt) { if (_currentInPlaceControl != null) { IInPlaceControl c = (_currentInPlaceControl as IInPlaceControl); if ((c != null) && !SelectedPropertyEnumerator.Property.Value.IsReadOnly(SelectedPropertyEnumerator)) { c.OnF4(); break; } } } PropertyVisibleDeepEnumerator nextEnum = new PropertyVisibleDeepEnumerator(_selectedPropertyEnum.Node); nextEnum.MoveNext(); Property nextProperty = nextEnum.Property; if (nextProperty != null) { Rectangle clientRect = ClientRectangle; Rectangle itemRect = GetAbsoluteItemRect(nextEnum); if (itemRect.Top < clientRect.Top) // Test if the item is above the top of the grid { while (true) { Win32Calls.SendMessage(Handle, Win32Calls.WM_VSCROLL, Win32Calls.MakeLong(Win32Calls.SB_LINEUP, 0), 0); itemRect = GetAbsoluteItemRect(nextEnum); if (itemRect.Top == clientRect.Top) break; } Win32Calls.SendMessage(Handle, Win32Calls.WM_VSCROLL, Win32Calls.MakeLong(Win32Calls.SB_ENDSCROLL, 0), 0); } else if (itemRect.Bottom > clientRect.Bottom) // Test if the item is below the bottom of the grid { // We scroll in a loop because the item may have a row height greater than the base row height // if the current selected item is the last one displayed // (TODO: we could be more performant by avoiding scrolls and directly calculating which property // needs to be the first displayed) _parentCtrl.BeginUpdate(); // To avoid the remancence of the inplace control do { Win32Calls.SendMessage(Handle, Win32Calls.WM_VSCROLL, Win32Calls.MakeLong(Win32Calls.SB_LINEDOWN, 0), 0); itemRect = GetAbsoluteItemRect(nextEnum); } while ((itemRect.Bottom > clientRect.Bottom) && (itemRect.Top > clientRect.Top)); Win32Calls.SendMessage(Handle, Win32Calls.WM_VSCROLL, Win32Calls.MakeLong(Win32Calls.SB_ENDSCROLL, 0), 0); _parentCtrl.EndUpdate(); } SelectProperty(nextEnum); } break; } case Keys.Left: // Closes the item if it is an expanded category case Keys.Subtract: { if ((e.KeyCode == Keys.Left) && (ModifierKeys == Keys.Control)) { SetLabelColumnWidthRatio((double)(LabelColumnWidth - 3) / (ClientRectangle.Width - LeftColumnWidth)); break; } if (SelectedPropertyEnumerator.Children.Count > 0) { Property property = SelectedPropertyEnumerator.Property; if (property.Expanded && HasOneVisibleChild(SelectedPropertyEnumerator)) { ExpandProperty(SelectedPropertyEnumerator, false); break; } } if (e.KeyCode == Keys.Subtract) break; goto case Keys.Up; } case Keys.Up: // Moves the selected item up { PropertyVisibleDeepEnumerator prevEnum = new PropertyVisibleDeepEnumerator(_selectedPropertyEnum.Node); prevEnum.MovePrev(); Property prevProperty = prevEnum.Property; if (prevProperty != null) { Rectangle clientRect = ClientRectangle; Rectangle itemRect = GetAbsoluteItemRect(prevEnum); if (itemRect.Top < clientRect.Top) { _firstDisplayedLine = 1; FirstDisplayedProperty = prevEnum; } else if (itemRect.Bottom > clientRect.Bottom) { while(true) { Win32Calls.SendMessage(Handle, Win32Calls.WM_VSCROLL, Win32Calls.MakeLong(Win32Calls.SB_LINEDOWN, 0), 0); itemRect = GetAbsoluteItemRect(prevEnum); if (itemRect.Bottom < clientRect.Bottom) break; } Win32Calls.SendMessage(Handle, Win32Calls.WM_VSCROLL, Win32Calls.MakeLong(Win32Calls.SB_ENDSCROLL, 0), 0); } SelectProperty(prevEnum); } break; } case Keys.Next: { Rectangle clientRect = ClientRectangle; int itemsPerPage = clientRect.Height / _basicPropertyHeight - 1; Rectangle itemRect = GetAbsoluteItemRect(SelectedPropertyEnumerator); // Find the item one page down int count = 0; PropertyEnumerator propEnum = SelectedPropertyEnumerator.GetVisibleDeepEnumerator(); int lineCount = (propEnum == FirstDisplayedProperty ? _firstDisplayedLine : 1); while ((count < itemsPerPage) && (propEnum != propEnum.RightBound)) { if (lineCount == propEnum.Property.HeightMultiplier) { propEnum.MoveNext(); lineCount = 1; } else lineCount++; count++; } // Selected item is above the grid ? if (itemRect.Bottom < clientRect.Top) { if (propEnum == propEnum.RightBound) { propEnum.MovePrev(); _firstDisplayedLine = propEnum.Property.HeightMultiplier; } else _firstDisplayedLine = lineCount; SelectProperty(propEnum); EnsureVisible(propEnum); } // Selected item is in or below the grid ? else { if (propEnum == propEnum.RightBound) // Not a complete page down because at the far bottom ? { propEnum.MovePrev(); lineCount = propEnum.Property.HeightMultiplier; PropertyVisibleDeepEnumerator propertyToSelectEnum = propEnum.GetVisibleDeepEnumerator(); count = itemsPerPage; while ((propEnum != _activePropertyCollection.GetVisibleDeepEnumerator().MoveFirst()) && (count > 0)) { if (lineCount > 1) lineCount--; else { propEnum.MovePrev(); lineCount = propEnum.Property.HeightMultiplier; } count--; } _firstDisplayedLine = lineCount; FirstDisplayedProperty = propEnum as PropertyVisibleDeepEnumerator; SelectProperty(propertyToSelectEnum); } else { // The grid height is to small to properly page down ? if (itemsPerPage < propEnum.Property.HeightMultiplier) { // Advance one item if (propEnum != _activePropertyCollection.GetVisibleDeepEnumerator().MoveLast()) { if (propEnum == SelectedPropertyEnumerator) propEnum.MoveNext(); _firstDisplayedLine = 1; FirstDisplayedProperty = propEnum as PropertyVisibleDeepEnumerator; SelectProperty(propEnum); } } else { FirstDisplayedProperty = SelectedPropertyEnumerator; SelectProperty(propEnum); } } } Invalidate(); break; } case Keys.Prior: { Rectangle clientRect = ClientRectangle; int itemsPerPage = clientRect.Height / _basicPropertyHeight - 1; // Find the item one page up int count = 0; PropertyVisibleDeepEnumerator enumerator = SelectedPropertyEnumerator.GetVisibleDeepEnumerator(); int lineCount = enumerator.Property.HeightMultiplier; while ((count < itemsPerPage) && (enumerator != _activePropertyCollection.GetVisibleDeepEnumerator().MoveFirst())) { if (lineCount == 1) { enumerator.MovePrev(); lineCount = enumerator.Property.HeightMultiplier; } else lineCount--; count++; } if ((count == 0) && (enumerator != _activePropertyCollection.GetVisibleDeepEnumerator().MoveFirst())) { enumerator.MovePrev(); count = 1; } Rectangle itemRect = GetAbsoluteItemRect(enumerator); // Is the new selected item in the grid ? if ((itemRect.Top >= clientRect.Top) && (itemRect.Bottom < clientRect.Bottom)) SelectProperty(enumerator); // Is the new selected item below the grid ? else if (itemRect.Bottom > clientRect.Bottom) { PropertyEnumerator currentEnum = enumerator.GetVisibleDeepEnumerator(); lineCount = 1; while((count > 0) && (currentEnum != _activePropertyCollection.GetVisibleDeepEnumerator().MoveFirst())) { if (lineCount == 1) { currentEnum.MovePrev(); lineCount = currentEnum.Property.HeightMultiplier; } else lineCount--; count--; } FirstDisplayedProperty = currentEnum as PropertyVisibleDeepEnumerator; SelectProperty(enumerator); } // Is the new selected item above the grid ? else if (itemRect.Top < clientRect.Top) { _firstDisplayedLine = 1; FirstDisplayedProperty = enumerator; SelectProperty(FirstDisplayedProperty); } Refresh(); break; } case Keys.Home: { Win32Calls.SetScrollPos(Handle, Win32Calls.SB_VERT, 0, true); _firstDisplayedPropertyEnumerator = _activePropertyCollection.GetVisibleDeepEnumerator(); _firstDisplayedPropertyEnumerator.MoveFirst(); _firstDisplayedLine = 1; SelectProperty(FirstDisplayedProperty); break; } case Keys.End: { Rectangle clientRect = ClientRectangle; _firstDisplayedPropertyEnumerator = _activePropertyCollection.GetVisibleDeepEnumerator(); _firstDisplayedPropertyEnumerator.MoveLast(); _firstDisplayedLine = 1; PropertyVisibleDeepEnumerator currentEnum = _firstDisplayedPropertyEnumerator.GetVisibleDeepEnumerator(); Rectangle itemRect = GetItemRect(currentEnum); while ((_firstDisplayedPropertyEnumerator != _activePropertyCollection.GetVisibleDeepEnumerator().MoveFirst()) && (clientRect.Bottom - itemRect.Bottom > _basicPropertyHeight)) { if (_firstDisplayedLine > 1) _firstDisplayedLine--; else { _firstDisplayedPropertyEnumerator.MovePrev(); _firstDisplayedLine = _firstDisplayedPropertyEnumerator.Property.HeightMultiplier; } itemRect = GetItemRect(currentEnum); } Win32Calls.SCROLLINFO si = new Win32Calls.SCROLLINFO(); si.cbSize = Marshal.SizeOf(si); si.fMask = Win32Calls.SIF_PAGE | Win32Calls.SIF_RANGE; Win32Calls.GetScrollInfo(Handle, Win32Calls.SB_VERT, ref si); Win32Calls.SetScrollPos(Handle, Win32Calls.SB_VERT, si.nMax - (si.nPage - 1), true); PropertyVisibleDeepEnumerator lastEnum = _activePropertyCollection.GetVisibleDeepEnumerator(); lastEnum.MoveLast(); SelectProperty(lastEnum); break; } case Keys.A: { if (e.Control) { if (_multiSelectMode == PropertyGrid.MultiSelectModes.SameLevel) { // Find the parent of the concerned level PropertyEnumerator ancestorEnum; if (SelectedPropertyEnumerator.Children.Count == 0) ancestorEnum = SelectedPropertyEnumerator.Parent; else ancestorEnum = SelectedPropertyEnumerator; // And browse all properties at this level and under PropertyEnumerator propEnum = ancestorEnum.Children.GetVisibleDeepEnumerator(); propEnum.RestrictedToThisLevelAndUnder = true; while(propEnum != ancestorEnum.Children.RightBound) { if (_parentCtrl.OnValidateMultiSelection(SelectedPropertyEnumerator, propEnum as PropertyVisibleDeepEnumerator)) { propEnum.Property.SelectedInternal = true; _multiSelectedItems.Add(propEnum); } propEnum.MoveNext(); } Invalidate(); } else if (_multiSelectMode == PropertyGrid.MultiSelectModes.Global) { PropertyEnumerator propEnum = _activePropertyCollection.GetVisibleDeepEnumerator(); propEnum.MoveFirst(); while (propEnum != propEnum.RightBound) { if ((propEnum != SelectedPropertyEnumerator) && (propEnum.Children.Count == 0)) { if (_parentCtrl.OnValidateMultiSelection(SelectedPropertyEnumerator, propEnum as PropertyVisibleDeepEnumerator)) { propEnum.Property.SelectedInternal = true; _multiSelectedItems.Add(propEnum); } } propEnum.MoveNext(); } Invalidate(); } } break; } } } base.OnKeyDown(e); }