Example #1
0
        // perform a hit test on the specific point
        // POINT is in screen coordinates
        static internal NativeMethods.LVHITTESTINFO_INTERNAL SubitemHitTest (IntPtr hwnd, int item, NativeMethods.Win32Point pt)
        {
            // Allocate a local LVHITTESTINFO struct.
            NativeMethods.LVHITTESTINFO_INTERNAL hitTest = new NativeMethods.LVHITTESTINFO_INTERNAL ();

            // Set the point of interest.
            hitTest.pt = pt;
            hitTest.iItem = item;

            int result = -1;

            // convert to client
            if (Misc.MapWindowPoints(IntPtr.Zero, hwnd, ref hitTest.pt, 1))
            {
                unsafe
                {
                    // Send the LVM_SUBITEMHITTEST message to the list view owner process.
                    // This is ok to do even for non LVS_REPORT listview, since in that case this
                    // message will behaive like LVM_HITTEST
                    if (Misc.IsComctrlV6OnOsVerV6orHigher(hwnd))
                    {
                        NativeMethods.LVHITTESTINFO_V6 hitTestNative = new NativeMethods.LVHITTESTINFO_V6(hitTest);
                        result = XSendMessage.XSendGetIndex(hwnd, NativeMethods.LVM_SUBITEMHITTEST, IntPtr.Zero, new IntPtr(&hitTestNative), Marshal.SizeOf(hitTestNative.GetType()));
                        hitTest.flags = hitTestNative.flags;
                        hitTest.iItem = hitTestNative.iItem;
                        hitTest.iGroup = hitTestNative.iGroup;
                    }
                    else
                    {
                        NativeMethods.LVHITTESTINFO hitTestNative = new NativeMethods.LVHITTESTINFO(hitTest);
                        result = XSendMessage.XSendGetIndex(hwnd, NativeMethods.LVM_SUBITEMHITTEST, IntPtr.Zero, new IntPtr(&hitTestNative), Marshal.SizeOf(hitTestNative.GetType()));
                        hitTest.flags = hitTestNative.flags;
                        hitTest.iItem = hitTestNative.iItem;
                    }
                }
            }

            if (result == -1)
            {
                hitTest.iSubItem = hitTest.iItem = -1;
            }

            return hitTest;
        }
        // Returns a Proxy element corresponding to the specified screen coordinates.
        internal override ProxySimple ElementProviderFromPoint (int x, int y)
        {
            NativeMethods.Win32Point pt = new NativeMethods.Win32Point (x, y);
            NativeMethods.LVHITTESTINFO_INTERNAL hitTest = WindowsListView.SubitemHitTest (_hwnd, pt);

            if ((hitTest.flags & NativeMethods.LVHT_EX_GROUP_HEADER) != 0)
            {
                return this;
            }

            if ((hitTest.flags & NativeMethods.LVHT_ONITEM) != 0 && hitTest.iItem >= 0)
            {
                // create the item
                return new ListViewItem (_hwnd, this, hitTest.iItem);
            }

            // If we did not land on an item we may be at a subset link these only exist
            // in v6 comctrl and vista or later.
            if (_isComctrlV6OnOsVerV6orHigher)
            {
                // Allocate a local LVHITTESTINFO struct.
                NativeMethods.LVHITTESTINFO_V6 hitTestNative = new NativeMethods.LVHITTESTINFO_V6(hitTest);
                unsafe
                {
                    XSendMessage.XSendGetIndex(_hwnd, NativeMethods.LVM_HITTEST, new IntPtr(-1), new IntPtr(&hitTestNative), Marshal.SizeOf(hitTestNative.GetType()));
                }

                if ((hitTestNative.flags & NativeMethods.LVHT_EX_GROUP_SUBSETLINK) != 0)
                {
                    GroupManager.GroupInfo groupInfo = GetGroupInfo (_hwnd, ID);
                    int [] items = groupInfo._items;
                    if (groupInfo._count <= 0 || groupInfo._count > items.Length)
                    {
                        return null;
                    }
                    
                    int index = items [groupInfo._count - 1];
                    return CreateGroupSubsetLink(index + 1);
                }
            }
            
            return this;
        }