// ------------------------------------------------------ // // Internal Methods // // ------------------------------------------------------ #region Internal Methods // Static implementation for the bounding rectangle. This is used by // ElementProviderFromPoint to avoid to have to create for a simple // boundary check // param "item", ID for the scrollbar bit // param "sbFlag", SBS_ WindowLong equivallent flag static internal Rect GetHorizontalScrollbarBitBoundingRectangle(IntPtr hwnd, WindowsScrollBar.ScrollBarItem item, NativeMethods.ScrollBarInfo sbi) { // Horizontal Scrollbar NativeMethods.Win32Rect rc = new NativeMethods.Win32Rect(sbi.xyThumbTop, sbi.rcScrollBar.top, sbi.xyThumbBottom, sbi.rcScrollBar.bottom); if (!Misc.MapWindowPoints(hwnd, IntPtr.Zero, ref rc, 2)) { return Rect.Empty; } // Since the scrollbar position is already mapped, restore them back rc.top = sbi.rcScrollBar.top; rc.bottom = sbi.rcScrollBar.bottom; NativeMethods.SIZE sizeArrow; using (ThemePart themePart = new ThemePart(hwnd, "SCROLLBAR")) { sizeArrow = themePart.Size((int)ThemePart.SCROLLBARPARTS.SBP_ARROWBTN, 0); } // check that the 2 buttons can hold in the scroll bar bool fThumbVisible = sbi.rcScrollBar.right - sbi.rcScrollBar.left >= 5 * sizeArrow.cx / 2; if (sbi.rcScrollBar.right - sbi.rcScrollBar.left < 2 * sizeArrow.cx) { // the scroll bar is tiny, need to shrink the button sizeArrow.cx = (sbi.rcScrollBar.right - sbi.rcScrollBar.left) / 2; } // // Builds prior to Vista 5359 failed to correctly account for RTL scrollbar layouts. // if ((Environment.OSVersion.Version.Major < 6) && (Misc.IsLayoutRTL(hwnd))) { if (item == WindowsScrollBar.ScrollBarItem.UpArrow) { item = WindowsScrollBar.ScrollBarItem.DownArrow; } else if (item == WindowsScrollBar.ScrollBarItem.DownArrow) { item = WindowsScrollBar.ScrollBarItem.UpArrow; } else if (item == WindowsScrollBar.ScrollBarItem.LargeIncrement) { item = WindowsScrollBar.ScrollBarItem.LargeDecrement; } else if (item == WindowsScrollBar.ScrollBarItem.LargeDecrement) { item = WindowsScrollBar.ScrollBarItem.LargeIncrement; } } switch (item) { case WindowsScrollBar.ScrollBarItem.UpArrow : rc.left = sbi.rcScrollBar.left; rc.right = sbi.rcScrollBar.left + sizeArrow.cx; break; case WindowsScrollBar.ScrollBarItem.LargeIncrement : if (fThumbVisible) { rc.left = rc.right; rc.right = sbi.rcScrollBar.right - sizeArrow.cx; } else { rc.left = rc.right = sbi.rcScrollBar.left + sizeArrow.cx; } break; case WindowsScrollBar.ScrollBarItem.Thumb : if (!fThumbVisible) { rc.left = rc.right = sbi.rcScrollBar.left + sizeArrow.cx; } break; case WindowsScrollBar.ScrollBarItem.LargeDecrement : if (fThumbVisible) { rc.right = rc.left; rc.left = sbi.rcScrollBar.left + sizeArrow.cx; } else { rc.left = rc.right = sbi.rcScrollBar.left + sizeArrow.cx; } break; case WindowsScrollBar.ScrollBarItem.DownArrow : rc.left = sbi.rcScrollBar.right - sizeArrow.cx; rc.right = sbi.rcScrollBar.right; break; } // Don't need to normalize, OSVer conditional block converts to absolute coordinates. return rc.ToRect(false); }
// ------------------------------------------------------ // // 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; }
// Returns a Proxy element corresponding to the specified screen coordinates. internal override ProxySimple ElementProviderFromPoint (int x, int y) { for (SItem item = SItem.LargeDecrement; (int) item <= (int) SItem.LargeIncrement; item = (SItem) ((int) item + 1)) { NativeMethods.Win32Rect rc = new NativeMethods.Win32Rect (SliderItem.GetBoundingRectangle (_hwnd, item, _fHorizontal)); if (Misc.PtInRect(ref rc, x, y)) { return CreateSliderItem (item); } } return null; }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods static internal bool IsGripPresent(IntPtr hwnd, bool onStatusBar) { NativeMethods.Win32Rect client = new NativeMethods.Win32Rect(); if (!Misc.GetClientRectInScreenCoordinates(hwnd, ref client)) { return false; } // According to the documentation of GetClientRect, the left and top members are zero. So if // they are negitive the control must be minimized, therefore the grip is not present. if (client.left < 0 && client.top < 0 ) { return false; } NativeMethods.SIZE sizeGrip = GetGripSize(hwnd, onStatusBar); if (!onStatusBar) { // When not on a status bar the grip should be out side of the client area. sizeGrip.cx *= -1; sizeGrip.cy *= -1; } if (Misc.IsLayoutRTL(hwnd)) { int x = client.left + (int)(sizeGrip.cx / 2); int y = client.bottom - (int)(sizeGrip.cy / 2); int hit = Misc.ProxySendMessageInt(hwnd, NativeMethods.WM_NCHITTEST, IntPtr.Zero, NativeMethods.Util.MAKELPARAM(x, y)); return hit == NativeMethods.HTBOTTOMLEFT; } else { int x = client.right - (int)(sizeGrip.cx / 2); int y = client.bottom - (int)(sizeGrip.cy / 2); int hit = Misc.ProxySendMessageInt(hwnd, NativeMethods.WM_NCHITTEST, IntPtr.Zero, NativeMethods.Util.MAKELPARAM(x, y)); return hit == NativeMethods.HTBOTTOMRIGHT; } }
// determine the number of lines that are visible in the Edit control. // if there is no scrollbar then this is the actual number of lines displayed. internal int LinesPerPage() { int linePerPage = 0; if (Misc.IsBitSet(WindowStyle, NativeMethods.WS_VSCROLL)) { // we call GetScrollInfo and return the size of the "page" NativeMethods.ScrollInfo si = new NativeMethods.ScrollInfo(); si.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(NativeMethods.ScrollInfo)); si.fMask = NativeMethods.SIF_ALL; bool ok = Misc.GetScrollInfo(WindowHandle, NativeMethods.SB_VERT, ref si); linePerPage = ok ? si.nPage : 0; if (IsMultiline && linePerPage <= 0) { linePerPage = 1; } } else { NativeMethods.Win32Rect rect = new NativeMethods.Win32Rect(); if (Misc.GetClientRect(_hwnd, ref rect) && !rect.IsEmpty) { NativeMethods.SIZE size; string s = new string('E', 1); GetTextExtentPoint32(s, out size); if (size.cy != 0) { linePerPage = (rect.bottom - rect.top) / size.cy; } } } return linePerPage; }
internal static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] ref NativeMethods.Win32Rect rect, int cPoints);
// Returns a Proxy element corresponding to the specified screen coordinates. internal override ProxySimple ElementProviderFromPoint(int x, int y) { ProxySimple proxyElement = null; // Convert screen to client coords. NativeMethods.Win32Point pt = new NativeMethods.Win32Point(x, y); if (Misc.MapWindowPoints(System.IntPtr.Zero, _hwnd, ref pt, 1)) { // GetClientRect NativeMethods.Win32Rect clientRect = new NativeMethods.Win32Rect(); if(Misc.GetClientRect(_hwnd, ref clientRect)) { if (Misc.PtInRect(ref clientRect, pt.x, pt.y)) { int column = (pt.x - _altTabInfo.ptStart.x) / _altTabInfo.cxItem; int row = (pt.y - _altTabInfo.ptStart.y) / _altTabInfo.cyItem; if (column >= 0 && column < Columns && row >= 0 && row < Rows) { proxyElement = CreateAltTabItem(ItemIndex(row, column)); } } } } if (proxyElement == null) { proxyElement = base.ElementProviderFromPoint(x, y); } return proxyElement; }
static internal bool IsItemVisible(ref Rect parentRect, ref Rect itemRect) { NativeMethods.Win32Rect itemRc = new NativeMethods.Win32Rect(itemRect); NativeMethods.Win32Rect parentRc = new NativeMethods.Win32Rect(parentRect); NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0); // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API // does not modify clientRect or itemRect return IntersectRect(ref intersection, ref parentRc, ref itemRc); }
internal static extern IntPtr MonitorFromRect(ref NativeMethods.Win32Rect rect, int dwFlags);
internal static extern bool GetWindowRect(IntPtr hWnd, [In, Out] ref NativeMethods.Win32Rect rect);
public static extern bool GetMenuItemRect(IntPtr hWnd, IntPtr hMenu, int uItem, out NativeMethods.Win32Rect lprcItem);
internal static extern bool UnionRect(out NativeMethods.Win32Rect rcDst, ref NativeMethods.Win32Rect rc1, ref NativeMethods.Win32Rect rc2);
public static extern bool IntersectRect(ref NativeMethods.Win32Rect rcDest, ref NativeMethods.Win32Rect rc1, ref NativeMethods.Win32Rect rc2);
// Returns a Proxy element corresponding to the specified screen coordinates. internal override ProxySimple ElementProviderFromPoint (int x, int y) { for (ScrollBarItem item = ScrollBarItem.UpArrow; (int) item <= (int) ScrollBarItem.DownArrow; item = (ScrollBarItem) ((int) item + 1)) { NativeMethods.Win32Rect rc = new NativeMethods.Win32Rect(WindowsScrollBarBits.GetBoundingRectangle(_hwnd, this, item, _sbFlag)); if (Misc.PtInRect(ref rc, x, y)) { return new WindowsScrollBarBits (_hwnd, this, (int) item, _sbFlag); } } return this; }
//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ #region Private Methods private NativeMethods.Win32Rect GetBoundingRect() { int columns = this._altTab._altTabInfo.cColumns; int cxItem = this._altTab._altTabInfo.cxItem; int cyItem = this._altTab._altTabInfo.cyItem; int row = _item / columns; int column = _item % columns; NativeMethods.Win32Point ptStart = this._altTab._altTabInfo.ptStart; int left = ptStart.x + column * cxItem; int top = ptStart.y + row * cyItem; NativeMethods.Win32Rect itemRect = new NativeMethods.Win32Rect(left, top, left + cxItem, top + cyItem); if(!Misc.MapWindowPoints(_hwnd, IntPtr.Zero, ref itemRect, 2)) { // MapWindowPoints() failed. itemRect = NativeMethods.Win32Rect.Empty; } return itemRect; }
internal static bool GetClientRectInScreenCoordinates(IntPtr hwnd, ref NativeMethods.Win32Rect rc) { rc = NativeMethods.Win32Rect.Empty; if (!GetClientRect(hwnd, ref rc)) { return false; } NativeMethods.Win32Point leftTop = new NativeMethods.Win32Point(rc.left, rc.top); if (!MapWindowPoints(hwnd, IntPtr.Zero, ref leftTop, 1)) { return false; } NativeMethods.Win32Point rightBottom = new NativeMethods.Win32Point(rc.right, rc.bottom); if (!MapWindowPoints(hwnd, IntPtr.Zero, ref rightBottom, 1)) { return false; } rc = new NativeMethods.Win32Rect(leftTop.x, leftTop.y, rightBottom.x, rightBottom.y); return true; }
internal static IRawElementProviderSimple Create(IntPtr hwnd, int idChild) { if (!UnsafeNativeMethods.IsWindow(hwnd)) { return null; } System.Diagnostics.Debug.Assert(idChild == 0, string.Format(CultureInfo.CurrentCulture, "Invalid Child Id, idChild == {2}\n\rClassName: \"{0}\"\n\rhwnd = 0x{1:x8}", Misc.ProxyGetClassName(hwnd), hwnd.ToInt32(), idChild)); NativeMethods.Win32Rect clientRect = new NativeMethods.Win32Rect(); NativeMethods.Win32Rect windowRect = new NativeMethods.Win32Rect(); try { bool hasNonClientControls = // Note: GetClientRect will do MapWindowsPoints Misc.GetClientRectInScreenCoordinates(hwnd, ref clientRect) && Misc.GetWindowRect(hwnd, ref windowRect) && !windowRect.Equals(clientRect); if(hasNonClientControls || WindowsFormsHelper.IsWindowsFormsControl(hwnd)) { return new NonClientArea(hwnd); } return null; } catch (ElementNotAvailableException) { return null; } }
// This constructor should only be called with LVGROUP is a 32 bit structure internal TOOLINFO_64(NativeMethods.TOOLINFO item) { cbSize = Marshal.SizeOf(typeof(TOOLINFO_64)); uFlags = item.uFlags; hwnd = (long)item.hwnd; uId = item.uId; rect = item.rect; hinst = (long)item.hinst; pszText = (long)item.pszText; lParam = (long)item.lParam; }
// Process all the Element Properties internal override object GetElementProperty (AutomationProperty idProp) { if (idProp == AutomationElement.AcceleratorKeyProperty) { string acceleratorKey = AcceleratorKey; if (!string.IsNullOrEmpty(acceleratorKey)) return AcceleratorKey; } else if (idProp == AutomationElement.IsEnabledProperty) { // If an element in the parent chain is disabled there is not point in checking the menu if (!Misc.IsEnabled(_hwnd)) return false; return IsEnabledMenu; } else if (idProp == AutomationElement.AccessKeyProperty) { return GetAccessKey(); } else if (idProp == AutomationElement.IsKeyboardFocusableProperty) { return _type != MenuItemType.Spacer; } else if (idProp == AutomationElement.HasKeyboardFocusProperty) { // The check for the focused window fails!!! return IsFocused (); } else if (idProp == AutomationElement.IsOffscreenProperty) { // Even if the menu item that is the parent to a popup menu is off the screen // the popup menu will be displayed on the screen, so must override the // default action of checking the parent. Rect itemRect = BoundingRectangle; if (itemRect.IsEmpty) { return true; } // if this element is not on any monitor than it is off the screen. NativeMethods.Win32Rect itemWin32Rect = new NativeMethods.Win32Rect(itemRect); return UnsafeNativeMethods.MonitorFromRect(ref itemWin32Rect, UnsafeNativeMethods.MONITOR_DEFAULTTONULL) == IntPtr.Zero; } return base.GetElementProperty (idProp); }
internal static extern IntPtr SendMessageTimeout(IntPtr hwnd, int uMsg, IntPtr wParam, ref NativeMethods.Win32Rect lParam, int flags, int uTimeout, out IntPtr result);
// Returns a Proxy element corresponding to the specified screen coordinates. internal override ProxySimple ElementProviderFromPoint (int x, int y) { for (SpinItem item = SpinItem.DownArrow; item <= SpinItem.UpArrow; item++) { NativeMethods.Win32Rect rc = new NativeMethods.Win32Rect (SpinButtonItem.GetBoundingRectangle (_hwnd, item)); if (Misc.PtInRect(ref rc, x, y)) { return CreateSpinButtonItem (item); } } return this; }
// To test if a list view item is offscreen, we need to // take into account the fact that it may be obscured by // the list view header. internal override bool IsOffscreen() { IntPtr hwndHeader = WindowsListView.ListViewGetHeader(_hwnd); if (hwndHeader != IntPtr.Zero) { NativeMethods.Win32Rect listViewRect = new NativeMethods.Win32Rect(); NativeMethods.Win32Rect headerRect = new NativeMethods.Win32Rect(); if (Misc.GetWindowRect(hwndHeader, ref headerRect) && Misc.GetClientRectInScreenCoordinates(_hwnd, ref listViewRect)) { // Remove the listview header rect. listViewRect.top = headerRect.bottom; NativeMethods.Win32Rect itemRect = new NativeMethods.Win32Rect(BoundingRectangle); if (!listViewRect.IsEmpty && !Misc.IsItemVisible(ref listViewRect, ref itemRect)) { return true; } } } return false; }
// Same as a click on one of the button Up or Down void IInvokeProvider.Invoke () { // Make sure that the control is enabled if (!SafeNativeMethods.IsWindowEnabled(_hwnd)) { throw new ElementNotEnabledException(); } // NOTE: The GetBoundingRectangel() will swap the buttons to retrieve // the correct rectangle based on the WS_EX_LAYOUTRTL bit. But the // SendMessages WM_LBUTTONDOWN and WM_LBUTTONUP also swaps the buttons // on the WS_EX_LAYOUTRTL bit. So need to send the center point of // button before the swap to get the SendMessage to apply it to the // correct button. int item = _item; // If the control is horizontal and the WS_EX_LAYOUTRTL is set need to // swap the button order if (IsHorizontal(_hwnd) && Misc.IsLayoutRTL(_hwnd)) { item = 1 - item; } // does the control have vertical scrolling buttons Rect rc = GetBoundingRectangle(_hwnd, (WindowsUpDown.SpinItem)item); NativeMethods.Win32Rect updownRect = new NativeMethods.Win32Rect(); if (!Misc.GetWindowRect(_hwnd, ref updownRect)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } int x = (int) rc.Left - updownRect.left + (int) rc.Width / 2; int y = (int) rc.Top - updownRect.top + (int) rc.Height / 2; IntPtr center = NativeMethods.Util.MAKELPARAM (x, y); // the message does not seems to operate, fake a mouse action instead Misc.ProxySendMessage(_hwnd, NativeMethods.WM_LBUTTONDOWN, (IntPtr)NativeMethods.MK_LBUTTON, center); Misc.ProxySendMessage(_hwnd, NativeMethods.WM_LBUTTONUP, (IntPtr)NativeMethods.MK_LBUTTON, center); }
// ------------------------------------------------------ // // 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; }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods static internal Rect GetBoundingRectangle(IntPtr hwnd, WindowsUpDown.SpinItem item) { NativeMethods.Win32Rect updownRect = new NativeMethods.Win32Rect(); if (!Misc.GetWindowRect(hwnd, ref updownRect)) { return Rect.Empty; } bool fHorz = IsHorizontal(hwnd); // If the control is horizontal and the WS_EX_LAYOUTRTL is set need to // swap the button order if (fHorz && Misc.IsLayoutRTL(hwnd)) { item = item == SpinItem.DownArrow ? SpinItem.UpArrow : SpinItem.DownArrow; } switch (item) { case WindowsUpDown.SpinItem.DownArrow: if (fHorz) { int width = (updownRect.right - updownRect.left); updownRect.right = updownRect.left + width / 2; } else { int height = (updownRect.bottom - updownRect.top); updownRect.bottom = updownRect.top + height / 2; } // Don't need to normalize, GetWindowRect returns screen coordinates. return updownRect.ToRect(false); case WindowsUpDown.SpinItem.UpArrow: if (fHorz) { int width = (updownRect.right - updownRect.left); updownRect.left = updownRect.left + width / 2; } else { int height = (updownRect.bottom - updownRect.top); updownRect.top = updownRect.top + height / 2; } // Don't need to normalize, GetWindowRect returns screen coordinates. return updownRect.ToRect(false); } return Rect.Empty; }
// ------------------------------------------------------ // // Internal Methods // // ------------------------------------------------------ #region Internal Methods // Static implementation for the bounding rectangle. This is used by // ElementProviderFromPoint to avoid to have to create for a simple // boundary check // param "item", ID for the scrollbar bit // param "sbFlag", SBS_ WindowLong equivallent flag static internal Rect GetVerticalScrollbarBitBoundingRectangle(IntPtr hwnd, WindowsScrollBar.ScrollBarItem item, NativeMethods.ScrollBarInfo sbi) { NativeMethods.Win32Rect rc = new NativeMethods.Win32Rect(sbi.rcScrollBar.left, sbi.xyThumbTop, sbi.rcScrollBar.right, sbi.xyThumbBottom); if (!Misc.MapWindowPoints(hwnd, IntPtr.Zero, ref rc, 2)) { return Rect.Empty; } // Vertical Scrollbar // Since the scrollbar position is already mapped, restore them back rc.left = sbi.rcScrollBar.left; rc.right = sbi.rcScrollBar.right; NativeMethods.SIZE sizeArrow; using (ThemePart themePart = new ThemePart(hwnd, "SCROLLBAR")) { sizeArrow = themePart.Size((int)ThemePart.SCROLLBARPARTS.SBP_ARROWBTN, 0); } // check that the 2 buttons can hold in the scroll bar bool fThumbVisible = sbi.rcScrollBar.bottom - sbi.rcScrollBar.top >= 5 * sizeArrow.cy / 2; if (sbi.rcScrollBar.bottom - sbi.rcScrollBar.top < 2 * sizeArrow.cy) { // the scroll bar is tiny, need to shrink the button sizeArrow.cy = (sbi.rcScrollBar.bottom - sbi.rcScrollBar.top) / 2; } switch (item) { case WindowsScrollBar.ScrollBarItem.UpArrow : rc.top = sbi.rcScrollBar.top; rc.bottom = sbi.rcScrollBar.top + sizeArrow.cy; break; case WindowsScrollBar.ScrollBarItem.LargeIncrement : if (fThumbVisible) { rc.top = rc.bottom; rc.bottom = sbi.rcScrollBar.bottom - sizeArrow.cy; } else { rc.top = rc.bottom = sbi.rcScrollBar.top + sizeArrow.cy; } break; case WindowsScrollBar.ScrollBarItem.Thumb : if (!fThumbVisible) { rc.top = rc.bottom = sbi.rcScrollBar.top + sizeArrow.cy; } break; case WindowsScrollBar.ScrollBarItem.LargeDecrement : if (fThumbVisible) { rc.bottom = rc.top; rc.top = sbi.rcScrollBar.top + sizeArrow.cy; } else { rc.top = rc.bottom = sbi.rcScrollBar.top + sizeArrow.cy; } break; case WindowsScrollBar.ScrollBarItem.DownArrow : rc.top = sbi.rcScrollBar.bottom - sizeArrow.cy; rc.bottom = sbi.rcScrollBar.bottom; break; } // Don't need to normalize, OSVer conditional block converts to absolute coordinates. return rc.ToRect(false); }
//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ #region Private Methods private NativeMethods.Win32Rect BoundingRect() { NativeMethods.Win32Rect itemRect = new NativeMethods.Win32Rect(); Misc.ProxySendMessage(_hwnd, NativeMethods.LB_GETITEMRECT, new IntPtr(_item), ref itemRect); return Misc.MapWindowPoints(_hwnd, IntPtr.Zero, ref itemRect, 2) ? itemRect : NativeMethods.Win32Rect.Empty; }
// Check if a point is within the client Rect of a window static protected bool PtInClientRect (IntPtr hwnd, int x, int y) { NativeMethods.Win32Rect rc = new NativeMethods.Win32Rect (); if (!Misc.GetClientRect(hwnd, ref rc)) { return false; } if (!Misc.MapWindowPoints(hwnd, IntPtr.Zero, ref rc, 2)) { return false; } return x >= rc.left && x < rc.right && y >= rc.top && y < rc.bottom; }
// Returns a Proxy element corresponding to the specified screen coordinates. internal override ProxySimple ElementProviderFromPoint (int x, int y) { NativeMethods.Win32Rect listboxrect = new NativeMethods.Win32Rect (); Misc.GetClientRectInScreenCoordinates(_hwnd, ref listboxrect); if (Misc.PtInRect(ref listboxrect, x, y)) { int ret = Misc.ProxySendMessageInt(_hwnd, NativeMethods.LB_ITEMFROMPOINT, IntPtr.Zero, NativeMethods.Util.MAKELPARAM(x - listboxrect.left, y - listboxrect.top)); if (NativeMethods.Util.HIWORD(ret) == 0) { int index = NativeMethods.Util.LOWORD(ret); return CreateListboxItem(index); } } return base.ElementProviderFromPoint (x, y); }
// Returns a Proxy element corresponding to the specified screen coordinates. internal override ProxySimple ElementProviderFromPoint (int x, int y) { int x1 = x; int y1 = y; NativeMethods.Win32Rect rebarRect = new NativeMethods.Win32Rect (); if (!Misc.GetWindowRect(_hwnd, ref rebarRect)) { return null; } if (x >= rebarRect.left && x <= rebarRect.right && y >= rebarRect.top && y <= rebarRect.bottom) { x = x - rebarRect.left; y = y - rebarRect.top; NativeMethods.Win32Point pt = new NativeMethods.Win32Point (x, y); int BandID = getRebarBandIDFromPoint (pt); if (-1 != BandID) { return CreateRebarItem (BandID).ElementProviderFromPoint (x1, y1); } } return null; }
ITextRangeProvider ITextProvider.RangeFromPoint(Point screenLocation) { // convert screen to client coordinates. // (Essentially ScreenToClient but MapWindowPoints accounts for window mirroring using WS_EX_LAYOUTRTL.) NativeMethods.Win32Point clientLocation = (NativeMethods.Win32Point)screenLocation; if (!Misc.MapWindowPoints(IntPtr.Zero, WindowHandle, ref clientLocation, 1)) { return null; } // we have to deal with the possibility that the coordinate is inside the window rect // but outside the client rect. in that case we just scoot it over so it is at the nearest // point in the client rect. NativeMethods.Win32Rect clientRect = new NativeMethods.Win32Rect(); if (!Misc.GetClientRect(WindowHandle, ref clientRect)) { return null; } clientLocation.x = Math.Max(clientLocation.x, clientRect.left); clientLocation.x = Math.Min(clientLocation.x, clientRect.right); clientLocation.y = Math.Max(clientLocation.y, clientRect.top); clientLocation.y = Math.Min(clientLocation.y, clientRect.bottom); // get the character at those client coordinates int start = CharFromPosEx(clientLocation); return new WindowsEditBoxRange(this, start, start); }
// Check if a point is within the client Rect of a window internal static bool PtInWindowRect(IntPtr hwnd, int x, int y) { NativeMethods.Win32Rect rc = new NativeMethods.Win32Rect(); if (!GetWindowRect(hwnd, ref rc)) { return false; } return x >= rc.left && x < rc.right && y >= rc.top && y < rc.bottom; }
// send an EM_GETRECT message to find out the bounding rectangle internal Rect GetRect() { NativeMethods.Win32Rect rect = new NativeMethods.Win32Rect(); Misc.ProxySendMessage(WindowHandle, NativeMethods.EM_GETRECT, IntPtr.Zero, ref rect); return new Rect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); }
// this is to determine is an item is visible. The assumption is that the items here are not hwnds // and that they are clipped by there parent. For example this is called by the WindowsListBox. // In that case the hwnd is the list box and the itemRect would be a list item this code checks to see // if the item is scrolled out of view. static internal bool IsItemVisible(IntPtr hwnd, ref NativeMethods.Win32Rect itemRect) { NativeMethods.Win32Rect clientRect = new NativeMethods.Win32Rect(0, 0, 0, 0); if (!GetClientRectInScreenCoordinates(hwnd, ref clientRect)) return false; NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0); // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API // does not modify clientRect or itemRect return IntersectRect(ref intersection, ref clientRect, ref itemRect); }
internal void GetVisibleRangePoints(out int start, out int end) { start = 0; end = 0; NativeMethods.Win32Rect rect = new NativeMethods.Win32Rect(); if (Misc.GetClientRect(_hwnd, ref rect) && !rect.IsEmpty) { NativeMethods.SIZE size; string s = new string('E', 1); GetTextExtentPoint32(s, out size); NativeMethods.Win32Point ptStart = new NativeMethods.Win32Point((int)(rect.left + size.cx / 4), (int)(rect.top + size.cy / 4)); NativeMethods.Win32Point ptEnd = new NativeMethods.Win32Point((int)(rect.right - size.cx / 8), (int)(rect.bottom - size.cy / 4)); start = CharFromPosEx(ptStart); end = CharFromPosEx(ptEnd); if (start > 0) { Point pt = PosFromChar(start); if (pt.X < rect.left) { start++; } } } else { // multi-line edit controls are handled differently than single-line edit controls. if (IsMultiline) { // get the line number of the first visible line and start the range at // the beginning of that line. int firstLine = GetFirstVisibleLine(); start = LineIndex(firstLine); // calculate the line number of the first line scrolled off the bottom and // end the range at the beginning of that line. end = LineIndex(firstLine + LinesPerPage()); } else { // single-line edit control // the problem is that using a variable-width font the number of characters visible // depends on the text that is in the edit control. so we can't just divide the // width of the edit control by the width of a character. // so instead we do a binary search of the characters from the first visible character // to the end of the text to find the visibility boundary. Rect r = GetRect(); int limit = GetTextLength(); start = GetFirstVisibleChar(); int lo = start; // known visible int hi = limit; // known non-visible while (lo + 1 < hi) { int mid = (lo + hi) / 2; Point pt = PosFromChar(mid); if (pt.X >= r.Left && pt.X < r.Right) { lo = mid; } else { hi = mid; } } // trim off one character unless the range is empty or reaches the end. end = hi > start && hi < limit ? hi - 1 : hi; } } }
internal override bool IsOffscreen() { Rect itemRect = BoundingRectangle; if (itemRect.IsEmpty) { return true; } // Sub-TreeViewItems are not with in the parents bounding rectangle. So check if // the sub item is visible with in the whole control. ProxySimple parent; ProxySimple current = this; do { parent = current.GetParent(); if (parent is WindowsTreeView) { break; } current = parent; } while (parent != null); if (parent != null) { if ((bool)parent.GetElementProperty(AutomationElement.IsOffscreenProperty)) { return true; } // Now check to see if this item in visible on its parent Rect parentRect = parent.BoundingRectangle; if (!parentRect.IsEmpty && !Misc.IsItemVisible(ref parentRect, ref itemRect)) { return true; } } // if this element is not on any monitor than it is off the screen. NativeMethods.Win32Rect itemWin32Rect = new NativeMethods.Win32Rect(itemRect); return UnsafeNativeMethods.MonitorFromRect(ref itemWin32Rect, UnsafeNativeMethods.MONITOR_DEFAULTTONULL) == IntPtr.Zero; }
// This constructor should only be called with TOOLINFO is a 64 bit structure internal TOOLINFO_32(NativeMethods.TOOLINFO item) { cbSize = Marshal.SizeOf(typeof(TOOLINFO_32)); uFlags = item.uFlags; hwnd = item.hwnd.ToInt32(); uId = item.uId; rect = item.rect; hinst = unchecked((int)item.hinst); pszText = 0; lParam = unchecked((int)item.lParam); }