// Is focus set to the specified item protected override bool IsFocused () { NativeMethods.LVGROUP_V6 groupInfo = new NativeMethods.LVGROUP_V6(); groupInfo.Init(Marshal.SizeOf(typeof(NativeMethods.LVGROUP_V6))); groupInfo.iGroupID = _groupId; groupInfo.mask = NativeMethods.LVGF_STATE; groupInfo.stateMask = NativeMethods.LVGS_SUBSETLINKFOCUSED; // Note: return code of GetGroupInfo() is not reliable. XSendMessage.GetGroupInfo(_hwnd, ref groupInfo); // ignore return code. return (groupInfo.state & NativeMethods.LVGS_SUBSETLINKFOCUSED) != 0; }
private static unsafe GroupManager InitializeManager(IntPtr hwnd) { bool isComctrlV6OnOsVerV6orHigher = Misc.IsComctrlV6OnOsVerV6orHigher(hwnd); int itemCount = WindowsListView.GetItemCount(hwnd); NativeMethods.LVITEM_V6 item = new NativeMethods.LVITEM_V6(); item.mask = NativeMethods.LVIF_GROUPID; // The only place where the GroupManager gets constructed GroupManager manager = new GroupManager(itemCount, hwnd, isComctrlV6OnOsVerV6orHigher); if (isComctrlV6OnOsVerV6orHigher) { NativeMethods.LVITEMINDEX ii = new NativeMethods.LVITEMINDEX(-1, -1); int flags = NativeMethods.LVNI_VISIBLEONLY | NativeMethods.LVNI_VISIBLEORDER; // When a listview is being "grouped by" an item may be in more than one group. The itemCount // is the number of unique items. This loop may iterate for more than the unique items in the group. // We are taking advantage of that fact the the array list will expand if there are alot of duplicates. while (XSendMessage.XSend (hwnd, NativeMethods.LVM_GETNEXTITEMINDEX, new IntPtr(&ii), flags, Marshal.SizeOf(ii.GetType()))) { // need to convert the item id to a group id NativeMethods.LVGROUP_V6 groupInfo = new NativeMethods.LVGROUP_V6(); groupInfo.Init(Marshal.SizeOf(typeof(NativeMethods.LVGROUP_V6))); groupInfo.mask = NativeMethods.LVGF_GROUPID; bool lresult = XSendMessage.XSend(hwnd, NativeMethods.LVM_GETGROUPINFOBYINDEX, new IntPtr(ii.iGroup), new IntPtr(&groupInfo), Marshal.SizeOf(typeof(NativeMethods.LVGROUP_V6))); if (!lresult) { if (groupInfo.iGroupID == -1) { // A -1 here means that there are no duplicates in this grouped listview so // we have to get the group the old way. This is done for performance reasons. break; } // no group for this item should never happen. // If it ever does the other items might ok so just keep going. continue; } if (!manager.Add(groupInfo.iGroupID, ii.iItem)) { // we had problem adding item to the needed group at this point it makes no // sense to continue System.Diagnostics.Debug.Assert(false, "Cannot add item to the needed group"); return null; } } } bool sortNeeded = false; // If the code above did not yield anything try this way. This will work for // listviews pre Vista and grouped listviews in vista that don't have duplicate items. if (manager.GroupCount() == 0) { // if we get the groups this way they need to be sorted. The code above brings them in sorted. sortNeeded = true; int current = 0; while (current < itemCount) { item.iItem = current; if (XSendMessage.GetItem(hwnd, ref item) && manager.Add(item.iGroupID, item.iItem)) { current++; } else { // we had problem adding item to the needed group at this point it makes no // sense to continue System.Diagnostics.Debug.Assert(false, "Cannot add item to the needed group"); return null; } } } // Sort items within the group int groupsCount = manager.GroupCount(); for (int i = 0; i < groupsCount; i++) { Group group = (Group)manager._groups[i]; Array.Sort(group.Items, 0, group.Count, new SortGroupItems(hwnd)); } // Depending on how we got the group info we may need to sort it. // In vista the the listview can put the list items in the correct order. // Pre vista or old ui (v5) will always need to be sorted. if (sortNeeded) { // Sort groups manager._groups.Sort(new SortGroups(hwnd)); } return manager; }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods // get focused element internal static ProxySimple GetFocusInGroup (IntPtr hwnd, ProxyFragment parent) { int index = WindowsListView.GetItemNext(hwnd, -1, NativeMethods.LVNI_FOCUSED); if (index != -1) { // get id of the group to which item belongs NativeMethods.LVITEM_V6 item = new NativeMethods.LVITEM_V6 (); item.mask = NativeMethods.LVIF_GROUPID; item.iItem = index; if (XSendMessage.GetItem(hwnd, ref item)) { WindowsListViewGroup group = new WindowsListViewGroup (hwnd, parent, item.iGroupID); return new ListViewItem (hwnd, group, index); } } else { // if none of the items have focus see if the focus is on the subset link // this only exists in v6 comctrl on vista or later. if (Misc.IsComctrlV6OnOsVerV6orHigher(hwnd)) { int groupIndex = (int)Misc.ProxySendMessage(hwnd, NativeMethods.LVM_GETFOCUSEDGROUP, IntPtr.Zero, IntPtr.Zero); // need to convert the item id to a group id NativeMethods.LVGROUP_V6 groupInfo = new NativeMethods.LVGROUP_V6(); groupInfo.Init(Marshal.SizeOf(typeof(NativeMethods.LVGROUP_V6))); groupInfo.mask = NativeMethods.LVGF_GROUPID; unsafe { bool lresult = XSendMessage.XSend(hwnd, NativeMethods.LVM_GETGROUPINFOBYINDEX, new IntPtr(groupIndex), new IntPtr(&groupInfo), Marshal.SizeOf(typeof(NativeMethods.LVGROUP_V6))); if (!lresult) { // no group for this item should never happen. return null; } } int groupId = groupInfo.iGroupID; groupInfo.Init(Marshal.SizeOf(typeof(NativeMethods.LVGROUP_V6))); groupInfo.iGroupID = groupId; groupInfo.mask = NativeMethods.LVGF_STATE; groupInfo.stateMask = NativeMethods.LVGS_SUBSETLINKFOCUSED; // Note: return code of GetGroupInfo() is not reliable. XSendMessage.GetGroupInfo(hwnd, ref groupInfo); // ignore return code. if ((groupInfo.state & NativeMethods.LVGS_SUBSETLINKFOCUSED) != 0) { GroupManager.GroupInfo groupManagerInfo = GetGroupInfo (hwnd, groupId); int [] items = groupManagerInfo._items; if (groupManagerInfo._count <= 0 || groupManagerInfo._count >= items.Length) { return null; } int sslIndex = items [groupManagerInfo._count - 1]; // The items array holds the list items in this group. If we have a subset link we // don't store it with the list items because it isn't really a list item. Instead we just // create the subset link proxy with an item index one more than the last index. WindowsListViewGroup group = new WindowsListViewGroup (hwnd, parent, groupId); return group.CreateGroupSubsetLink(sslIndex + 1); } else { return new WindowsListViewGroup (hwnd, parent, groupId); } } } return null; }
protected override bool IsFocused () { int groupIndex = (int)Misc.ProxySendMessage(_hwnd, NativeMethods.LVM_GETFOCUSEDGROUP, IntPtr.Zero, IntPtr.Zero); // need to convert the item id to a group id NativeMethods.LVGROUP_V6 groupInfo = new NativeMethods.LVGROUP_V6(); groupInfo.Init(Marshal.SizeOf(typeof(NativeMethods.LVGROUP_V6))); groupInfo.mask = NativeMethods.LVGF_GROUPID; unsafe { bool lresult = XSendMessage.XSend(_hwnd, NativeMethods.LVM_GETGROUPINFOBYINDEX, new IntPtr(groupIndex), new IntPtr(&groupInfo), Marshal.SizeOf(typeof(NativeMethods.LVGROUP_V6))); if (!lresult) { // no group for this item should never happen. return false; } } if (groupInfo.iGroupID == _groupID) { return true; } return false; }
// Returns the last child element in the raw hierarchy. internal override ProxySimple GetLastChild () { // return last item in this group GroupManager.GroupInfo groupInfo = GetGroupInfo (_hwnd, ID); // List view groups in vista can have an extra link at the end that says // something like "show all 11 items...". If one exists expose it as the last child. if (_isComctrlV6OnOsVerV6orHigher) { NativeMethods.LVGROUP_V6 group = new NativeMethods.LVGROUP_V6(); group.Init(Marshal.SizeOf(typeof(NativeMethods.LVGROUP_V6))); group.iGroupID = _groupID; group.mask = NativeMethods.LVGF_STATE; group.stateMask = NativeMethods.LVGS_SUBSETED; // Note: return code of GetGroupInfo() is not reliable. XSendMessage.GetGroupInfo(_hwnd, ref group); // ignore return code. // if we are not subseted then the last item is a regular listitem so // it is ok to fall through and let that be created. Otherwise we need to // create the subset link proxy. if ((group.state & NativeMethods.LVGS_SUBSETED) != 0) { int [] items = groupInfo._items; if (groupInfo._count <= 0 || groupInfo._count > items.Length) { return null; } int index = items [groupInfo._count - 1]; return CreateGroupSubsetLink(index + 1); } } if (groupInfo) { int [] items = groupInfo._items; if (groupInfo._count <= 0 || groupInfo._count > items.Length) { return null; } int index = items [groupInfo._count - 1]; return CreateListViewItem (index); } return null; }
// 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) { GroupManager.GroupInfo groupInfo = GetGroupInfo (_hwnd, ID); if (groupInfo) { int [] items = groupInfo._items; int current = child._item; // find the index of the current lvitem int nextLocation = groupInfo.IndexOf (current) + 1; //Array.IndexOf(items, current) + 1; if (nextLocation <= 0) { // No more siblings return null; } if (nextLocation < groupInfo._count) { return CreateListViewItem (items [nextLocation]); } // List view groups in vista can have an extra link at the end that says // somthing like "show all 11 items..." if (_isComctrlV6OnOsVerV6orHigher && nextLocation == groupInfo._count) { NativeMethods.LVGROUP_V6 group = new NativeMethods.LVGROUP_V6(); group.Init(Marshal.SizeOf(typeof(NativeMethods.LVGROUP_V6))); group.iGroupID = _groupID; group.mask = NativeMethods.LVGF_STATE; group.stateMask = NativeMethods.LVGS_SUBSETED; // Note: return code of GetGroupInfo() is not reliable. XSendMessage.GetGroupInfo(_hwnd, ref group); // ignore return code. // The items array holds the list items in this group. If we have a subset link we // don't store it with the list items because it isn't really a list item. Instead we just // create the subset link proxy with an item index one more than the last index. if ((group.state & NativeMethods.LVGS_SUBSETED) != 0) { return CreateGroupSubsetLink(items [groupInfo._count - 1] + 1); } } } return null; }