// detect if this listviewitem needs to support GridItem pattern static private bool IsImplementingGrid(IntPtr hwnd) { // in the detail mode, GridItem will be implemented on the subitem // and not item if (WindowsListView.IsDetailMode(hwnd)) { return(false); } return(WindowsListView.IsListMode(hwnd) || WindowsListView.ListViewAutoArrange(hwnd)); }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods // retrieve bounding rectangle of the listview checkbox internal static NativeMethods.Win32Rect ListViewCheckBoxRect(IntPtr hwnd, int item) { // Rare special case if (WindowsListView.FullRowSelect(hwnd) && WindowsListView.IsDetailMode(hwnd)) { // Get listview window rect NativeMethods.Win32Rect controlRectangle = NativeMethods.Win32Rect.Empty; if (!Misc.GetWindowRect(hwnd, ref controlRectangle)) { return(NativeMethods.Win32Rect.Empty); } // BOUNDS == SELECTBOUNDS, hence cannot rely on them // will rely on the ICON or LABEL // Try icon first since it is the closest to the checkbox NativeMethods.Win32Rect rc; if ((WindowsListView.GetItemRect(hwnd, item, NativeMethods.LVIR_ICON, out rc) && rc.left != rc.right) || (WindowsListView.GetItemRect(hwnd, item, NativeMethods.LVIR_LABEL, out rc) && rc.left != rc.right)) { int right = controlRectangle.left + (rc.left - controlRectangle.left); return(new NativeMethods.Win32Rect(controlRectangle.left, rc.top, right, rc.bottom)); } } else { // Very common, simple case NativeMethods.Win32Rect wholeItem; if (!WindowsListView.GetItemRect(hwnd, item, NativeMethods.LVIR_BOUNDS, out wholeItem)) { return(NativeMethods.Win32Rect.Empty); } NativeMethods.Win32Rect selectable; if (!WindowsListView.GetItemRect(hwnd, item, NativeMethods.LVIR_SELECTBOUNDS, out selectable)) { return(NativeMethods.Win32Rect.Empty); } if (Misc.IsControlRTL(hwnd)) { return(new NativeMethods.Win32Rect(selectable.right, wholeItem.top, wholeItem.right, wholeItem.bottom)); } else { return(new NativeMethods.Win32Rect(wholeItem.left, wholeItem.top, selectable.left, wholeItem.bottom)); } } return(NativeMethods.Win32Rect.Empty); }
// Scroll the specified headerItem horizontally into view. internal void ScrollIntoView(HeaderItem headerItem) { // Check if the parent is a ListView IntPtr hwndParent = NativeMethodsSetLastError.GetAncestor(_hwnd, NativeMethods.GA_PARENT); if (hwndParent != IntPtr.Zero) { if (Misc.GetClassName(hwndParent).IndexOf("SysListView32", StringComparison.Ordinal) >= 0) { // Determine the number of pixels or columns to scroll horizontally. int pixels = 0; int columns = 0; // Get first and last visible header items. HeaderItem firstVisibleHeaderItem; HeaderItem lastVisibleHeaderItem; GetVisibleHeaderItemRange(out firstVisibleHeaderItem, out lastVisibleHeaderItem); if (firstVisibleHeaderItem != null && firstVisibleHeaderItem._item > headerItem._item) { // Scroll backward. pixels = (int)(headerItem.BoundingRectangle.Left - firstVisibleHeaderItem.BoundingRectangle.Left); columns = headerItem._item - firstVisibleHeaderItem._item; } else if (lastVisibleHeaderItem != null && headerItem._item > lastVisibleHeaderItem._item) { // Scroll forward. pixels = (int)(headerItem.BoundingRectangle.Left - lastVisibleHeaderItem.BoundingRectangle.Left); columns = headerItem._item - lastVisibleHeaderItem._item; } int horizontalScrollAmount = 0; if (WindowsListView.IsListMode(hwndParent)) { // In list mode, LVM_SCROLL uses a column count. horizontalScrollAmount = columns; } else if (WindowsListView.IsDetailMode(hwndParent)) { // In details mode, LVM_SCROLL uses a pixel count. horizontalScrollAmount = pixels; } if (horizontalScrollAmount != 0) { Misc.ProxySendMessage(hwndParent, NativeMethods.LVM_SCROLL, new IntPtr(horizontalScrollAmount), IntPtr.Zero); } } } }
// Returns the next sibling element in the raw hierarchy. // Peripheral controls have always negative values. // Returns null if no next child internal override ProxySimple GetNextSibling(ProxySimple child) { int item = child._item; if (WindowsListView.IsDetailMode(_hwnd)) { item++; int countCol = GetSubItemCount(_hwnd); if (item >= 0 && item < countCol) { return(CreateListViewSubItem(item)); } } return(null); }
// ------------------------------------------------------ // // Constructors // //------------------------------------------------------ #region Constructors internal ListViewItem(IntPtr hwnd, ProxyFragment parent, int item) : base(hwnd, parent, item) { // Set the strings to return properly the properties. if (WindowsListView.IsDetailMode(hwnd)) { _cControlType = ControlType.DataItem; } else { _cControlType = ControlType.ListItem; } _fHasPersistentID = false; _fIsKeyboardFocusable = true; _isComctrlV6OnOsVerV6orHigher = Misc.IsComctrlV6OnOsVerV6orHigher(hwnd); }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods internal static int GetSubItemCount(IntPtr hwnd) { // Subitems are only available in details mode. if (WindowsListView.IsDetailMode(hwnd)) { IntPtr hwndHeader = WindowsListView.ListViewGetHeader(hwnd); if (hwndHeader == IntPtr.Zero) { return(0); } return(WindowsListView.HeaderItemCount(hwndHeader)); } return(-1); }
// Returns the first child element in the raw hierarchy. internal override ProxySimple GetFirstChild() { if (IsItemWithCheckbox(_hwnd, _item)) { return(CreateListViewItemCheckbox()); } else if (WindowsListView.IsDetailMode(_hwnd)) { int countCol = GetSubItemCount(_hwnd); if (countCol > 0) { return(CreateListViewSubItem(0)); } } return(null); }
// Returns the previous sibling element in the raw hierarchy. // Peripheral controls have always negative values. // Returns null is no previous internal override ProxySimple GetPreviousSibling(ProxySimple child) { int item = child._item; if (IsItemWithCheckbox(_hwnd, _item) && item == 0) { return(CreateListViewItemCheckbox()); } else if (WindowsListView.IsDetailMode(_hwnd)) { int countCol = GetSubItemCount(_hwnd); if (item > 0 && item < countCol) { return(CreateListViewSubItem(item - 1)); } } return(null); }
// retrieve number of columns in the group static private int GetColumnCount(IntPtr hwnd, int groupID) { if (WindowsListView.IsDetailMode(hwnd)) { // check group for validity if (IsGroupValid(hwnd, groupID)) { // When lv in the detail mode, Group will have as many columns // as there header items int column = ListViewItem.GetSubItemCount(hwnd); return((column <= -1) ? 0 : column); } return(-1); } return(GetCountOfItemsInDimension(hwnd, groupID, new IsNewItemInDimension(IsNewColumn))); }
// Obtain clickable point on the listviewitem // in the case when one doesnot exist return false private bool GetListviewitemClickablePoint(out NativeMethods.Win32Point clickPoint) { // When this method is called, lv was already scrolled vertically // hence item is visible veritcally clickPoint.x = clickPoint.y = 0; NativeMethods.Win32Rect itemRectangle; // Obtain rectangle if (!WindowsListView.GetItemRect(_hwnd, _item, NativeMethods.LVIR_LABEL, out itemRectangle)) { return(false); } if (WindowsListView.IsDetailMode(_hwnd) && !WindowsListView.FullRowSelect(_hwnd)) { // LVS_REPORT - possible that we may need to scroll horizontaly // NativeMethods.Win32Point pt = new NativeMethods.Win32Point(itemRectangle.left, 0); if (!Misc.MapWindowPoints(IntPtr.Zero, _hwnd, ref pt, 1)) { return(false); } // In client coordinates, hence negative indicates that item is to the left of lv client area if (pt.x < 0) { ((IScrollItemProvider)this).ScrollIntoView(); if (!WindowsListView.GetItemRect(_hwnd, _item, NativeMethods.LVIR_LABEL, out itemRectangle)) { return(false); } } } clickPoint.x = Math.Min((itemRectangle.left + 5), (itemRectangle.left + itemRectangle.right) / 2); clickPoint.y = (itemRectangle.top + itemRectangle.bottom) / 2; return(true); }
// Returns a Proxy element corresponding to the specified screen coordinates. internal override ProxySimple ElementProviderFromPoint(int x, int y) { // Test for the checkbox first if (IsItemWithCheckbox(_hwnd, _item)) { NativeMethods.Win32Rect checkboxRectangle = ListViewItemCheckbox.ListViewCheckBoxRect(_hwnd, _item); if (!checkboxRectangle.IsEmpty && Misc.PtInRect(ref checkboxRectangle, x, y)) { // listviewitem checkbox return(new ListViewItemCheckbox(_hwnd, this, _item, _checkbox)); } } if (WindowsListView.IsDetailMode(_hwnd)) { // test for subitem (returns either subitem or lvitem) return(ListViewSubItem.ElementProviderFromPoint(_hwnd, this, _item, x, y)); } return(this); }
// retrieve number of rows in the group static private int GetRowCount(IntPtr hwnd, int groupID) { if (WindowsListView.IsDetailMode(hwnd)) { // When lv in Detail mode (with items shown in groups) // each lvitem will live in their own row // we need to detect how many items belong to the group, // this would correspond to the number of rows GroupManager.GroupInfo groupInfo = GetGroupInfo(hwnd, groupID); if (groupInfo) { return(groupInfo._count); } // Good place to send Grid Invalid event return(-1); } return(GetCountOfItemsInDimension(hwnd, groupID, new IsNewItemInDimension(IsNewRow))); }
// Obtain the AutomationElement at an zero based absolute position in the grid. // Where 0,0 is top left IRawElementProviderSimple IGridProvider.GetItem(int row, int column) { int maxRow = GetRowCount(_hwnd, ID); int maxColumn = GetColumnCount(_hwnd, ID); if (row < 0 || row >= maxRow) { throw new ArgumentOutOfRangeException("row", row, SR.Get(SRID.GridRowOutOfRange)); } if (column < 0 || column >= maxColumn) { throw new ArgumentOutOfRangeException("column", column, SR.Get(SRID.GridColumnOutOfRange)); } if (WindowsListView.IsDetailMode(_hwnd)) { return(GetCellInDetailMode(row, column)); } return(GetCellInOtherModes(row, column, maxColumn)); }
// Expose the ability to retrieve count of columns in the Group's grid to the outside proxies // LVItem will be one of customer // Do not call when LV in the Detail mode static internal int GetColumnCountExternal(IntPtr hwnd, int groupID) { System.Diagnostics.Debug.Assert(!WindowsListView.IsDetailMode(hwnd), "GetColumnCountExternal: called when lv is in Detail mode"); return(GetCountOfItemsInDimension(hwnd, groupID, new IsNewItemInDimension(IsNewColumn))); }