//------------------------------------------------------
            //
            //  Internal Methods
            //
            //------------------------------------------------------

            #region Internal Methods

            // Returns the bounding rectangle of the control.
            internal static Rect GetBoundingRectangle(IntPtr hwnd, int item)
            {
                NativeMethods.Win32Rect rectW32 = NativeMethods.Win32Rect.Empty;

                unsafe
                {
                    if (!XSendMessage.XSend(hwnd, NativeMethods.RB_GETRECT, new IntPtr(item), new IntPtr(&rectW32), Marshal.SizeOf(rectW32.GetType()), XSendMessage.ErrorValue.Zero))
                    {
                        return(Rect.Empty);
                    }
                }

                if (!Misc.MapWindowPoints(hwnd, IntPtr.Zero, ref rectW32, 2))
                {
                    return(Rect.Empty);
                }

                // Work around a bug in the common control. Swap the X and Y value for vertical
                // rebar bands
                if (Misc.IsBitSet(Misc.GetWindowStyle(hwnd), (int)CommonControlStyles.CCS_VERT))
                {
                    return(new Rect(rectW32.left, rectW32.top, rectW32.bottom - rectW32.top, rectW32.right - rectW32.left));
                }
                else
                {
                    return(rectW32.ToRect(Misc.IsControlRTL(hwnd)));
                }
            }
        private unsafe int GetGroupHeaderHeight()
        {
            NativeMethods.LVGROUPMETRICS metric = new NativeMethods.LVGROUPMETRICS(sizeof(NativeMethods.LVGROUPMETRICS), NativeMethods.LVGMF_BORDERSIZE);
            XSendMessage.XSend(_hwnd, NativeMethods.LVM_GETGROUPMETRICS, IntPtr.Zero, new IntPtr(&(metric.cbSize)), metric.cbSize, XSendMessage.ErrorValue.NoCheck);

            return(metric.Top + padding);
        }
        // ------------------------------------------------------
        //
        // Internal Methods
        //
        // ------------------------------------------------------

        #region Internal Methods

        internal static int GetItemCount(IntPtr hwnd)
        {
            // The Display Property Dialog is doing something strange with the their tab control.  The
            // last tab is invisable. So if that is the case remove it from the count, since UIAutomation
            // can not do anything with it.
            int count = Misc.ProxySendMessageInt(hwnd, NativeMethods.TCM_GETITEMCOUNT, IntPtr.Zero, IntPtr.Zero);

            if (count > 0)
            {
                NativeMethods.Win32Rect rectW32 = NativeMethods.Win32Rect.Empty;
                bool result;
                unsafe
                {
                    result = XSendMessage.XSend(hwnd, NativeMethods.TCM_GETITEMRECT, new IntPtr(count - 1), new IntPtr(&rectW32), Marshal.SizeOf(rectW32.GetType()), XSendMessage.ErrorValue.Zero);
                }
                if (!result)
                {
                    count--;
                }
                if (rectW32.IsEmpty)
                {
                    count--;
                }
            }

            return(count);
        }
Пример #4
0
        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);
        }
Пример #5
0
        // Extract the internal Name property of the Windows Forms control using
        // the WM_GETCONTROLNAME message.
        static internal string GetControlName(IntPtr hwnd)
        {
            string winFormsID = "";

            if (XSendMessage.XSend(hwnd, WM_GETCONTROLNAME, new IntPtr(Misc.MaxLengthNameProperty), ref winFormsID, Misc.MaxLengthNameProperty))
            {
                return(winFormsID);
            }
            return(null);
        }
        // ------------------------------------------------------
        //
        // Private Methods
        //
        // ------------------------------------------------------

        #region Private Methods

        private unsafe NativeMethods.Win32Rect BoundingRect()
        {
            NativeMethods.Win32Rect rectW32 = new NativeMethods.Win32Rect();

            if (!XSendMessage.XSend(_hwnd, NativeMethods.TCM_GETITEMRECT, new IntPtr(_item), new IntPtr(&rectW32), Marshal.SizeOf(rectW32.GetType()), XSendMessage.ErrorValue.Zero))
            {
                return(NativeMethods.Win32Rect.Empty);
            }

            return(Misc.MapWindowPoints(_hwnd, IntPtr.Zero, ref rectW32, 2) ? rectW32 : NativeMethods.Win32Rect.Empty);
        }
            internal unsafe NativeMethods.Win32Rect GetGroupRect()
            {
                NativeMethods.Win32Rect rect = new NativeMethods.Win32Rect();
                bool isCollapsed             = WindowsListViewGroup.IsCollapsed(_hwnd, _groupID);

                rect.top = isCollapsed ? NativeMethods.LVGGR_HEADER : NativeMethods.LVGGR_GROUP;
                XSendMessage.XSend(_hwnd, NativeMethods.LVM_GETGROUPRECT,
                                   new IntPtr(_groupID), new IntPtr(&rect), Marshal.SizeOf(rect.GetType()));

                Misc.MapWindowPoints(_hwnd, IntPtr.Zero, ref rect, 2);

                return(rect);
            }
Пример #8
0
        // Sets the focus to this item.
        internal override bool SetFocus()
        {
            //
            // Send the link an LM_SETITEM message.
            //
            // Allocate a local LITEM struct.
            UnsafeNativeMethods.LITEM linkItem = new UnsafeNativeMethods.LITEM();

            // Fill in the coordinates about which we care.
            linkItem.mask      = NativeMethods.LIF_ITEMINDEX | NativeMethods.LIF_STATE;
            linkItem.iLink     = _item;
            linkItem.stateMask = NativeMethods.LIS_FOCUSED;
            linkItem.state     = NativeMethods.LIS_FOCUSED;

            unsafe
            {
                // Send the LM_SETITEM message.
                return(XSendMessage.XSend(_hwnd, NativeMethods.LM_SETITEM, IntPtr.Zero, new IntPtr(&linkItem), Marshal.SizeOf(linkItem.GetType())));
            }
        }
Пример #9
0
        private bool GetLinkItem(int item)
        {
            if (item < 0)
            {
                return(false);
            }

            // Set the members about which we care.
            _linkItem.mask      = NativeMethods.LIF_ITEMINDEX | NativeMethods.LIF_STATE;
            _linkItem.iLink     = item;
            _linkItem.state     = 0;
            _linkItem.stateMask = NativeMethods.LIS_ENABLED;

            unsafe
            {
                fixed(UnsafeNativeMethods.LITEM *pLinkItem = &_linkItem)
                {
                    return(XSendMessage.XSend(_hwnd, NativeMethods.LM_GETITEM, IntPtr.Zero, new IntPtr(pLinkItem), sizeof(UnsafeNativeMethods.LITEM)));
                }
            }
        }
Пример #10
0
        // Returns a Proxy element corresponding to the specified
        // screen coordinates.
        internal override ProxySimple ElementProviderFromPoint(int x, int y)
        {
            //
            // Send the link an LM_HITTEST message.
            //
            // Allocate a local hit test info struct.
            UnsafeNativeMethods.LHITTESTINFO HitTestInfo = new UnsafeNativeMethods.LHITTESTINFO();

            // Fill in the coordinates that we want to check.
            HitTestInfo.pt.x = x;
            HitTestInfo.pt.y = y;

            // Convert screen coordinates to client coordinates.
            if (!Misc.MapWindowPoints(IntPtr.Zero, _hwnd, ref HitTestInfo.pt, 1))
            {
                base.ElementProviderFromPoint(x, y);
            }

            // Fill in index and state info.
            HitTestInfo.item.mask      = NativeMethods.LIF_ITEMINDEX | NativeMethods.LIF_STATE;
            HitTestInfo.item.iLink     = 0;
            HitTestInfo.item.stateMask = NativeMethods.LIS_ENABLED;
            HitTestInfo.item.state     = 0;

            bool bGetItemResult;

            unsafe
            {
                // Send the LM_HITTEST message.
                bGetItemResult = XSendMessage.XSend(_hwnd, NativeMethods.LM_HITTEST, IntPtr.Zero, new IntPtr(&HitTestInfo), Marshal.SizeOf(HitTestInfo.GetType()));
            }

            if (bGetItemResult == true && HitTestInfo.item.iLink >= 0 && GetLinkItem(HitTestInfo.item.iLink))
            {
                return(CreateHyperlinkItem(_linkItem, HitTestInfo.item.iLink));
            }

            return(base.ElementProviderFromPoint(x, y));
        }
        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);
        }
            // Gets the bounding rectangle for this element
            private NativeMethods.Win32Rect BoundingRect()
            {
                // get index
                int index = OrderToIndex(_hwnd, _item);

                NativeMethods.Win32Rect rectW32 = NativeMethods.Win32Rect.Empty;

                bool result;

                unsafe
                {
                    result = XSendMessage.XSend(_hwnd, NativeMethods.HDM_GETITEMRECT, new IntPtr(index), new IntPtr(&rectW32), Marshal.SizeOf(rectW32.GetType()), XSendMessage.ErrorValue.Zero);
                }

                if (result)
                {
                    if (!Misc.MapWindowPoints(_hwnd, IntPtr.Zero, ref rectW32, 2))
                    {
                        return(NativeMethods.Win32Rect.Empty);
                    }

                    // Remove the space that is used to
                    if (!IsFilter())
                    {
                        // From the source code for the SysHeader control.
                        // This is the divider slop area. Selecting this area with the mouse does not select
                        // the header, it perpares the header/column to be resized.
                        int cxBorder = 8 * UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_CXBORDER);

                        if (Misc.IsLayoutRTL(_hwnd))
                        {
                            // Right to left mirroring style

                            // adjust the left margin
                            rectW32.left += cxBorder;
                            if (rectW32.left > rectW32.right)
                            {
                                rectW32.left = rectW32.right;
                            }

                            // adjust the right margin
                            if (_item > 0)
                            {
                                rectW32.right -= cxBorder;
                                if (rectW32.right < rectW32.left)
                                {
                                    rectW32.right = rectW32.left;
                                }
                            }
                        }
                        else
                        {
                            // adjust the left margin
                            if (_item > 0)
                            {
                                rectW32.left += cxBorder;
                                if (rectW32.left > rectW32.right)
                                {
                                    rectW32.left = rectW32.right;
                                }
                            }

                            // adjust the right margin
                            rectW32.right -= cxBorder;
                            if (rectW32.right < rectW32.left)
                            {
                                rectW32.right = rectW32.left;
                            }
                        }
                    }
                    return(rectW32);
                }

                return(NativeMethods.Win32Rect.Empty);
            }
Пример #13
0
        // Same as clicking on an hyperlink
        void IInvokeProvider.Invoke()
        {
            // Check that button can be clicked.
            //
            // @



            // Make sure that the control is enabled
            if (!SafeNativeMethods.IsWindowEnabled(_hwnd))
            {
                throw new ElementNotEnabledException();
            }

            if (!SafeNativeMethods.IsWindowVisible(_hwnd))
            {
                throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
            }

            //
            // Get the bounding rect for the window.
            //
            NativeMethods.Win32Rect BoundingRect = NativeMethods.Win32Rect.Empty;
            if (!Misc.GetWindowRect(_hwnd, ref BoundingRect))
            {
                return;
            }

            //
            // All we really need here are the height and the width,
            // so we don't even need to translate between screen
            // and client coordinates.
            //
            int width  = BoundingRect.right - BoundingRect.left;
            int height = BoundingRect.bottom - BoundingRect.top;

            //
            // Determine the point to click.
            //
            // @



            for (int Resolution = 10; Resolution > 0; --Resolution)
            {
                for (int x = 1; x <= width; x += Resolution)
                {
                    for (int y = 1; y <= height; y += Resolution)
                    {
                        //
                        // Send the link an LM_HITTEST message.
                        //
                        // Allocate a local hit test info struct.
                        UnsafeNativeMethods.LHITTESTINFO HitTestInfo = new UnsafeNativeMethods.LHITTESTINFO();

                        // Fill in the coordinates that we want to check.
                        HitTestInfo.pt.x = x;
                        HitTestInfo.pt.y = y;

                        // Fill in index and state info.
                        HitTestInfo.item.mask      = NativeMethods.LIF_ITEMINDEX | NativeMethods.LIF_STATE;
                        HitTestInfo.item.iLink     = 0;
                        HitTestInfo.item.stateMask = NativeMethods.LIS_ENABLED;
                        HitTestInfo.item.state     = 0;

                        bool bGetItemResult;
                        unsafe
                        {
                            // Send the LM_HITTEST message.
                            bGetItemResult = XSendMessage.XSend(_hwnd, NativeMethods.LM_HITTEST, IntPtr.Zero, new IntPtr(&HitTestInfo), Marshal.SizeOf(HitTestInfo.GetType()));
                        }

                        if (bGetItemResult == true && HitTestInfo.item.iLink == _item)
                        {
                            //
                            // N.B. [SEdmison]:
                            // This multiplication is essentially just
                            // a left shift by one word's width; in
                            // Win32 I'd just use my trusty MAKELONG macro,
                            // but C# doesn't give me that option.
                            //
                            Misc.ProxySendMessage(_hwnd, NativeMethods.WM_LBUTTONDOWN, IntPtr.Zero, NativeMethods.Util.MAKELPARAM(x, y));
                            Misc.ProxySendMessage(_hwnd, NativeMethods.WM_LBUTTONUP, IntPtr.Zero, NativeMethods.Util.MAKELPARAM(x, y));
                            return;
                        }
                    }
                }
            }
        }
Пример #14
0
            // ------------------------------------------------------
            //
            // Internal Methods
            //
            // ------------------------------------------------------

            #region Internal Methods

            // Returns the bounding rectangle of the control.
            internal static Rect GetBoundingRectangle(IntPtr hwnd, WindowsSlider.SItem item, bool fHorizontal)
            {
                NativeMethods.Win32Rect rcChannel = new NativeMethods.Win32Rect();
                rcChannel.left = rcChannel.right = rcChannel.top = rcChannel.bottom = 1000;

                unsafe
                {
                    XSendMessage.XSend(hwnd, NativeMethods.TBM_GETCHANNELRECT, IntPtr.Zero, new IntPtr(&rcChannel), Marshal.SizeOf(rcChannel.GetType()), XSendMessage.ErrorValue.NoCheck);
                }
                if (!Misc.MapWindowPoints(hwnd, IntPtr.Zero, ref rcChannel, 2))
                {
                    return(Rect.Empty);
                }

                NativeMethods.Win32Rect rcThumb = new NativeMethods.Win32Rect();
                rcThumb.left = rcThumb.right = rcThumb.top = rcThumb.bottom = 1000;

                unsafe
                {
                    XSendMessage.XSend(hwnd, NativeMethods.TBM_GETTHUMBRECT, IntPtr.Zero, new IntPtr(&rcThumb), Marshal.SizeOf(rcThumb.GetType()), XSendMessage.ErrorValue.NoCheck);
                }
                if (!Misc.MapWindowPoints(hwnd, IntPtr.Zero, ref rcThumb, 2))
                {
                    return(Rect.Empty);
                }

                if (fHorizontal)
                {
                    // When WS_EX_RTLREADING is set swap the increment and decrement bars.
                    if (Misc.IsLayoutRTL(hwnd))
                    {
                        if (item == SItem.LargeDecrement)
                        {
                            item = SItem.LargeIncrement;
                        }
                        else if (item == SItem.LargeIncrement)
                        {
                            item = SItem.LargeDecrement;
                        }
                    }

                    switch (item)
                    {
                    case WindowsSlider.SItem.LargeDecrement:
                        return(new Rect(rcChannel.left, rcChannel.top, rcThumb.left - rcChannel.left, rcChannel.bottom - rcChannel.top));

                    case WindowsSlider.SItem.Thumb:
                        return(new Rect(rcThumb.left, rcThumb.top, rcThumb.right - rcThumb.left, rcThumb.bottom - rcThumb.top));

                    case WindowsSlider.SItem.LargeIncrement:
                        return(new Rect(rcThumb.right, rcChannel.top, rcChannel.right - rcThumb.right, rcChannel.bottom - rcChannel.top));
                    }
                }
                else
                {
                    int dx = rcChannel.bottom - rcChannel.top;
                    int dy = rcChannel.right - rcChannel.left;

                    switch (item)
                    {
                    case WindowsSlider.SItem.LargeDecrement:
                        return(new Rect(rcChannel.left, rcChannel.top, dx, rcThumb.top - rcChannel.top));

                    case WindowsSlider.SItem.Thumb:
                        return(new Rect(rcThumb.left, rcThumb.top, rcThumb.right - rcThumb.left, rcThumb.bottom - rcThumb.top));

                    case WindowsSlider.SItem.LargeIncrement:
                        return(new Rect(rcChannel.left, rcThumb.bottom, dx, dy));
                    }
                }

                return(Rect.Empty);
            }
Пример #15
0
        //------------------------------------------------------
        //
        //  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);
        }
        unsafe private bool SetValue(DateTime DateTimeObject)
        {
            NativeMethods.SYSTEMTIME NewDateTime = ConvertDateTimeToSystemTime(DateTimeObject);

            return(XSendMessage.XSend(_hwnd, NativeMethods.DTM_SETSYSTEMTIME, IntPtr.Zero, new IntPtr(&NewDateTime), Marshal.SizeOf(NewDateTime.GetType())));
        }
        // Same as clicking on an hyperlink
        void IInvokeProvider.Invoke()
        {
            // Check that button can be clicked.
            //
            // This state could change anytime.
            //

            // Make sure that the control is enabled
            if (!SafeNativeMethods.IsWindowEnabled(_hwnd))
            {
                throw new ElementNotEnabledException();
            }

            if (!SafeNativeMethods.IsWindowVisible(_hwnd))
            {
                throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
            }

            //
            // Get the bounding rect for the window.
            //
            NativeMethods.Win32Rect BoundingRect = NativeMethods.Win32Rect.Empty;
            if (!Misc.GetWindowRect(_hwnd, ref BoundingRect))
            {
                return;
            }

            //
            // All we really need here are the height and the width,
            // so we don't even need to translate between screen
            // and client coordinates.
            //
            int width  = BoundingRect.right - BoundingRect.left;
            int height = BoundingRect.bottom - BoundingRect.top;

            //
            // Determine the point to click.
            //
            // We do this by scanning over the window's client
            // region hit-testing until we find a point that
            // corresponds to our link.  We start out by scanning
            // at a resolution of 10x10 pixels, starting from the
            // window's (1,1) coordinate, then reducing the resolution
            // if needed.  Thus the idea here is to scan quickly if
            // possible, but more thoroughly if absolutely necessary.
            //
            // Note:
            // I intentionally started scanning points starting from
            // (1,1) rather than from (0,0) just in case clicking the
            // border of a control is different than clicking inside
            // the border.
            //
            for (int Resolution = 10; Resolution > 0; --Resolution)
            {
                for (int x = 1; x <= width; x += Resolution)
                {
                    for (int y = 1; y <= height; y += Resolution)
                    {
                        //
                        // Send the link an LM_HITTEST message.
                        //
                        // Allocate a local hit test info struct.
                        UnsafeNativeMethods.LHITTESTINFO HitTestInfo = new UnsafeNativeMethods.LHITTESTINFO();

                        // Fill in the coordinates that we want to check.
                        HitTestInfo.pt.x = x;
                        HitTestInfo.pt.y = y;

                        // Fill in index and state info.
                        HitTestInfo.item.mask      = NativeMethods.LIF_ITEMINDEX | NativeMethods.LIF_STATE;
                        HitTestInfo.item.iLink     = 0;
                        HitTestInfo.item.stateMask = NativeMethods.LIS_ENABLED;
                        HitTestInfo.item.state     = 0;

                        bool bGetItemResult;
                        unsafe
                        {
                            // Send the LM_HITTEST message.
                            bGetItemResult = XSendMessage.XSend(_hwnd, NativeMethods.LM_HITTEST, IntPtr.Zero, new IntPtr(&HitTestInfo), Marshal.SizeOf(HitTestInfo.GetType()));
                        }

                        if (bGetItemResult == true && HitTestInfo.item.iLink == _item)
                        {
                            //
                            // N.B. [SEdmison]:
                            // This multiplication is essentially just
                            // a left shift by one word's width; in
                            // Win32 I'd just use my trusty MAKELONG macro,
                            // but C# doesn't give me that option.
                            //
                            Misc.ProxySendMessage(_hwnd, NativeMethods.WM_LBUTTONDOWN, IntPtr.Zero, NativeMethods.Util.MAKELPARAM(x, y));
                            Misc.ProxySendMessage(_hwnd, NativeMethods.WM_LBUTTONUP, IntPtr.Zero, NativeMethods.Util.MAKELPARAM(x, y));
                            return;
                        }
                    }
                }
            }
        }