public AutomationElement FindMatchingChild(Predicate<AutomationElement> pred) {
     IUIAutomationTreeWalker walker;
     pAutomation.get_ControlViewWalker(out walker);
     try {
         IUIAutomationElement elem;
         walker.GetFirstChildElement(pElement, out elem);
         while(elem != null) {
             AutomationElement ae = new AutomationElement(elem);
             if(pred(ae)) {
                 return ae;
             }
             IUIAutomationElement next;
             walker.GetNextSiblingElement(elem, out next);
             elem = next;
         }
         return null;
     }
     finally {
         if(walker != null) Marshal.ReleaseComObject(walker);
     }
 }
 public CachedListItemElement(AutomationElement elem, ExtendedItemsView parent)
 {
     Point offset = parent.GetWindowPos();
     offset = new Point(-offset.X, -offset.Y);
     Index = elem.GetItemIndex();
     Rectangle rect = elem.GetBoundingRect();
     rect.Offset(offset);
     FullRect = rect;
     bool foundLabel = false;
     bool foundIcon = false;
     foreach(AutomationElement child in elem.GetChildren()) {
         if(!foundLabel && child.GetAutomationId() == "System.ItemNameDisplay") {
             rect = child.GetBoundingRect();
             rect.Offset(offset);
             LabelRect = rect;
             if(foundIcon) break;
             foundLabel = true;
         }
         else if(!foundIcon && child.GetClassName() == "UIImage") {
             rect = child.GetBoundingRect();
             rect.Offset(offset);
             IconRect = rect;
             if(foundLabel) break;
             foundIcon = true;
         }
     }
 }
 public int HitTest(Point pt, bool ScreenCoords) {
     if(ListViewController == null) {
         return -1;
     }
     else if(fIsSysListView) {
         if(ScreenCoords) {
             PInvoke.ScreenToClient(ListViewController.Handle, ref pt);
         }
         LVHITTESTINFO structure = new LVHITTESTINFO();
         structure.pt.x = pt.X;
         structure.pt.y = pt.Y;
         IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(structure));
         Marshal.StructureToPtr(structure, ptr, false);
         int num = (int)PInvoke.SendMessage(ListViewController.Handle, LVM.HITTEST, IntPtr.Zero, ptr);
         Marshal.FreeHGlobal(ptr);
         return num;
     }
     else {
         if(!ScreenCoords) {
             PInvoke.ClientToScreen(ListViewController.Handle, ref pt);
         }
         AutomationElement elem = ListItemElementAt(pt);
         if(elem == null) return -1;
         StoredListItemElem = elem;
         StoredListItemIdx = elem.GetItemIndex();
         return StoredListItemIdx;
     }
 }
        public int GetFocusedItem() {
            if(!HasFocus()) {
                return -1;
            }

            if(fIsSysListView) {
                int count = GetItemCount();
                for(int i = 0; i < count; ++i) {
                    int state = (int)PInvoke.SendMessage(ListViewController.Handle, LVM.GETITEMSTATE, (IntPtr)i, (IntPtr)LVIS.FOCUSED);
                    if(state != 0) {
                        return i;
                    }
                }
                return -1;
            }
            else {
                AutomationElement elem = AutomationElement.FromKeyboardFocus();
                if(elem != null) {
                    // I don't like this solution.  TODO find a better one.
                    StoredListItemElem = elem;
                    StoredListItemIdx = elem.GetItemIndex();
                    return StoredListItemIdx;
                }
                return -1;
            }
        }
        protected override bool ListViewController_MessageCaptured(ref Message msg)
        {
            if (msg.Msg == WM_AFTERPAINT)
            {
                RefreshCache();
            }

            if (base.ListViewController_MessageCaptured(ref msg))
            {
                return(true);
            }

            switch (msg.Msg)
            {
            case LVM.SCROLL: {
                int amount = msg.WParam.ToInt32();
                SetRedraw(false);
                AutoMan.DoQuery(factory => {
                        AutomationElement elem = factory.FromHandle(Handle);
                        amount  /= SystemInformation.MouseWheelScrollDelta;
                        bool dec = amount < 0;
                        if (dec)
                        {
                            amount = -amount;
                        }
                        int lines = SystemInformation.MouseWheelScrollLines;
                        if (lines < 0)
                        {
                            elem.ScrollHorizontal(dec
                                    ? ScrollAmount.LargeDecrement
                                    : ScrollAmount.LargeIncrement, amount);
                        }
                        else
                        {
                            elem.ScrollHorizontal(dec
                                    ? ScrollAmount.SmallDecrement
                                    : ScrollAmount.SmallIncrement, amount * lines);
                        }
                        return(0);
                    });
                SetRedraw(true);
                return(true);
            }

            case WM.MOUSEACTIVATE: {
                int  res = (int)msg.Result;
                bool ret = OnMouseActivate(ref res);
                msg.Result = (IntPtr)res;
                return(ret);
            }

            case WM.LBUTTONDOWN: {
                // The ItemsView's window class doesn't have the CS_DBLCLKS
                // class style, which means we won't be receiving the
                // WM.LBUTTONDBLCLK message.  We'll just have to make do
                // without...
                Int64 now = DateTime.Now.Ticks;
                Point pt  = QTUtility2.PointFromLPARAM(msg.LParam);
                if ((now - lastLButtonTime) / 10000 <= SystemInformation.DoubleClickTime)
                {
                    Size size = SystemInformation.DoubleClickSize;
                    if (Math.Abs(pt.X - lastLButtonPoint.X) <= size.Width)
                    {
                        if (Math.Abs(pt.Y - lastLButtonPoint.Y) <= size.Height)
                        {
                            lastLButtonTime = 0;
                            if (OnDoubleClick(pt))
                            {
                                return(true);
                            }
                            if (HitTest(pt, false) > -1)
                            {
                                // Explorer includes an option to make
                                // single-clicking activate items.
                                // TODO: Support that.
                                if (OnItemActivated(Control.ModifierKeys))
                                {
                                    return(true);
                                }
                            }
                            return(false);
                        }
                    }
                }
                lastLButtonPoint = pt;
                lastLButtonTime  = now;
                return(false);
            }

            case WM.MOUSEMOVE: {
                Point pt = QTUtility2.PointFromLPARAM(msg.LParam);
                if (pt != lastMouseMovePoint)
                {
                    lastMouseMovePoint = pt;
                    if (focusedElement != null)
                    {
                        if (hotElement == null && focusedElement.FullRect.Contains(pt))
                        {
                            PInvoke.PostMessage(Handle, (uint)WM_AFTERPAINT, IntPtr.Zero, IntPtr.Zero);
                        }
                        else if (hotElement != null && hotElement.Index == focusedElement.Index && !focusedElement.FullRect.Contains(pt))
                        {
                            PInvoke.PostMessage(Handle, (uint)WM_AFTERPAINT, IntPtr.Zero, IntPtr.Zero);
                        }
                    }
                }
                break;
            }

            case WM.MOUSELEAVE:
                if (focusedElement != null)
                {
                    if (hotElement != null && hotElement.Index == focusedElement.Index)
                    {
                        PInvoke.PostMessage(Handle, (uint)WM_AFTERPAINT, IntPtr.Zero, IntPtr.Zero);
                    }
                }
                break;

            case WM.KEYDOWN:
                if (OnKeyDown((Keys)msg.WParam))
                {
                    return(true);
                }
                if ((Keys)msg.WParam == Keys.Enter)
                {
                    return(OnItemActivated(Control.ModifierKeys));
                }
                break;

            case WM.LBUTTONUP:
            case WM.RBUTTONUP:
            case WM.MBUTTONUP:
                RefreshCache();
                break;

            case WM.NOTIFY: {
                NMHDR nmhdr = (NMHDR)Marshal.PtrToStructure(msg.LParam, typeof(NMHDR));
                if (nmhdr.code == -530 /* TTN_NEEDTEXT */)
                {
                    NMTTDISPINFO dispinfo = (NMTTDISPINFO)Marshal.PtrToStructure(msg.LParam, typeof(NMTTDISPINFO));
                    if ((dispinfo.uFlags & 0x20 /* TTF_TRACK */) != 0)
                    {
                        return(OnGetInfoTip(ShellBrowser.GetFocusedIndex(), true));
                    }
                    else
                    {
                        int i = GetHotItem();
                        if (i != -1 && IsTrackingItemName())
                        {
                            return(OnGetInfoTip(i, false));
                        }
                    }
                }
                break;
            }
            }
            return(false);
        }
        protected override bool HandleCursorLoop(Keys key)
        {
            int focusedIdx = ShellBrowser.GetFocusedIndex();
            int itemCount  = ShellBrowser.GetItemCount();
            int selectMe   = -1;
            int viewMode   = ShellBrowser.ViewMode;

            switch (viewMode)
            {
            case FVM.CONTENT:
            case FVM.DETAILS:
                if (key == Keys.Up && focusedIdx == 0)
                {
                    selectMe = itemCount - 1;
                }
                else if (key == Keys.Down && focusedIdx == itemCount - 1)
                {
                    selectMe = 0;
                }
                break;

            case FVM.ICON:
            case FVM.SMALLICON:
            case FVM.THUMBNAIL:
            case FVM.TILE:
            case FVM.LIST:
                Keys KeyNextItem, KeyPrevItem, KeyNextPage, KeyPrevPage;
                if (viewMode == FVM.LIST)
                {
                    KeyNextItem = Keys.Down;
                    KeyPrevItem = Keys.Up;
                    KeyNextPage = Keys.Right;
                    KeyPrevPage = Keys.Left;
                }
                else
                {
                    KeyNextItem = Keys.Right;
                    KeyPrevItem = Keys.Left;
                    KeyNextPage = Keys.Down;
                    KeyPrevPage = Keys.Up;
                }
                int pageCount = AutoMan.DoQuery(factory => {
                    AutomationElement elem = factory.FromHandle(Handle);
                    if (elem == null)
                    {
                        return(-1);
                    }
                    return(viewMode == FVM.LIST ? elem.GetRowCount() : elem.GetColumnCount());
                });
                if (pageCount == -1)
                {
                    return(false);
                }
                int page = focusedIdx % pageCount;
                if (key == KeyNextItem && (page == pageCount - 1 || focusedIdx == itemCount - 1))
                {
                    selectMe = focusedIdx - page;
                }
                else if (key == KeyPrevItem && page == 0)
                {
                    selectMe = Math.Min(focusedIdx + pageCount - 1, itemCount - 1);
                }
                else if (key == KeyNextPage && focusedIdx + pageCount >= itemCount)
                {
                    selectMe = page;
                }
                else if (key == KeyPrevPage && focusedIdx < pageCount)
                {
                    int x = itemCount - focusedIdx - 1;
                    selectMe = x - x % pageCount + focusedIdx;
                }
                break;
            }
            if (selectMe >= 0)
            {
                ShellBrowser.SelectItem(selectMe);
                return(true);
            }
            else
            {
                return(false);
            }
        }