Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / UIAutomation / Win32Providers / MS / Internal / AutomationProxies / WindowsSysHeader.cs / 1 / WindowsSysHeader.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: Win32 SysHeader32 proxy // // History: // Jean-Francois Peyroux, alexsn - Created (in DotNet) // 2003/08/08 - alexsn Updated for WCP // // //--------------------------------------------------------------------------- using System; using System.Collections; using System.Globalization; using System.Runtime.InteropServices; using System.ComponentModel; using System.Text; using System.Windows.Automation; using System.Windows.Automation.Provider; using System.Windows; using System.Diagnostics; using MS.Win32; namespace MS.Internal.AutomationProxies { // Windows SysHeader32 proxy // NOTE: Since this proxy has its own HWND, it will be always discovered by UIAutomation // and placed where it should be // we MUST NEVER create a hard connection between us and header (via _parent) ourselves class WindowsSysHeader: ProxyHwnd { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors internal WindowsSysHeader (IntPtr hwnd) : base( hwnd, null, 0) { _cControlType = ControlType.Header; _fIsContent = false; _sAutomationId = "Header"; // This string is a non-localizable string // support for events _createOnEvent = new WinEventTracker.ProxyRaiseEvents (RaiseEvents); } #endregion Constructors #region Proxy Create // Static Create method called by UIAutomation to create this proxy. // returns null if unsuccessful internal static IRawElementProviderSimple Create(IntPtr hwnd, int idChild, int idObject) { return Create(hwnd, idChild); } internal static IRawElementProviderSimple Create(IntPtr hwnd, int idChild) { WindowsSysHeader header = new WindowsSysHeader(hwnd); if (idChild != 0) { return header.CreateHeaderItem(idChild - 1); } return header; } internal static void RaiseEvents (IntPtr hwnd, int eventId, object idProp, int idObject, int idChild) { if (idObject != NativeMethods.OBJID_VSCROLL && idObject != NativeMethods.OBJID_HSCROLL) { ProxyFragment header = new WindowsSysHeader(hwnd); AutomationProperty property = idProp as AutomationProperty; if (property == TablePattern.ColumnHeadersProperty || property == TablePattern.RowHeadersProperty) { // Check if the parent is a ListView IntPtr hwndParent = UnsafeNativeMethods.GetAncestor (hwnd, NativeMethods.GA_PARENT); if (hwndParent != IntPtr.Zero) { if (Misc.GetClassName(hwndParent).IndexOf("SysListView32", StringComparison.Ordinal) >= 0) { // Notify the Listview that the header Change WindowsListView wlv = (WindowsListView) WindowsListView.Create (hwndParent, 0); if (wlv != null) { wlv.DispatchEvents (eventId, idProp, idObject, idChild); } } } } else { if (idProp == InvokePattern.InvokedEvent) { ProxySimple headerItem = new HeaderItem(hwnd, header, idChild); headerItem.DispatchEvents(eventId, idProp, idObject, idChild); } else { header.DispatchEvents(eventId, idProp, idObject, idChild); } } } } #endregion //------------------------------------------------------ // // Patterns Implementation // //----------------------------------------------------- #region ProxyFragment Interface // 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) { // Determine how many items are in the list view. int item = child._item; return item + 1 < Length ? CreateHeaderItem (item + 1) : null; } // Returns the previous sibling element in the raw hierarchy. // Peripheral controls have always negative values. // Returns null is no previous internal override ProxySimple GetPreviousSibling (ProxySimple child) { // If the index of the previous node would be out of range... int item = child._item; return item > 0 ? CreateHeaderItem (item - 1) : null; } // Returns the first child element in the raw hierarchy. internal override ProxySimple GetFirstChild () { return Length > 0 ? CreateHeaderItem (0) : null; } // Returns the last child element in the raw hierarchy. internal override ProxySimple GetLastChild () { int count = Length; return count > 0 ? CreateHeaderItem (count - 1) : null; } // Returns a Proxy element corresponding to the specified screen coordinates. internal override ProxySimple ElementProviderFromPoint (int x, int y) { NativeMethods.HDHITTESTINFO HitTestInfo = new NativeMethods.HDHITTESTINFO(); HitTestInfo.pt = new NativeMethods.Win32Point (x, y); int index = -1; if (Misc.MapWindowPoints(IntPtr.Zero, _hwnd, ref HitTestInfo.pt, 1)) { unsafe { index = XSendMessage.XSendGetIndex(_hwnd, NativeMethods.HDM_HITTEST, IntPtr.Zero, new IntPtr(&HitTestInfo), Marshal.SizeOf(HitTestInfo.GetType())); } } // make sure that hit-test happened on the header item itself if (index != -1 && (NativeMethods.HHT_ONHEADER == (HitTestInfo.flags & 0x000F))) { return CreateHeaderItem (GetItemFromIndex (index)); } return this; } // Returns an item corresponding to the focused element (if there is one), or null otherwise. internal override ProxySimple GetFocus () { int item = Misc.ProxySendMessageInt(_hwnd, NativeMethods.HDM_GETFOCUSEDITEM, IntPtr.Zero, IntPtr.Zero); if (item < Length) return CreateHeaderItem (item); return null; } #endregion ProxyFragment Interface #region ProxySimple Interface // Process all the Logical and Raw Element Properties internal override object GetElementProperty(AutomationProperty idProp) { if (idProp == AutomationElement.OrientationProperty) { return Misc.IsBitSet(WindowStyle, NativeMethods.HDS_VERT) ? OrientationType.Vertical : OrientationType.Horizontal; } return base.GetElementProperty(idProp); } //Gets the localized name internal override string LocalizedName { get { return ST.Get(STID.LocalizedNameWindowsSysHeader); } } #endregion ProxySimple Interface // ------------------------------------------------------ // // Private Methods // // ------------------------------------------------------ #region Private Methods private void GetVisibleHeaderItemRange( out HeaderItem firstVisibleHeaderItem, out HeaderItem lastVisibleHeaderItem) { firstVisibleHeaderItem = null; lastVisibleHeaderItem = null; for (HeaderItem headerItem = GetFirstChild() as HeaderItem; headerItem != null; headerItem = GetNextSibling(headerItem) as HeaderItem) { bool isOffscreen = (bool) headerItem.GetElementProperty(AutomationElement.IsOffscreenProperty); if (!isOffscreen) { // Header item is visible. if (firstVisibleHeaderItem == null) { firstVisibleHeaderItem = headerItem; } lastVisibleHeaderItem = headerItem; } } } // Scroll the specified headerItem horizontally into view. internal void ScrollIntoView(HeaderItem headerItem) { // Check if the parent is a ListView IntPtr hwndParent = UnsafeNativeMethods.GetAncestor (_hwnd, NativeMethods.GA_PARENT); if (hwndParent != IntPtr.Zero) { if (Misc.GetClassName(hwndParent).IndexOf("SysListView32", StringComparison.Ordinal) >= 0) { // Determine the number of pixels or columns to scroll horizontally. int pixels = 0; int columns = 0; // Get first and last visible header items. HeaderItem firstVisibleHeaderItem; HeaderItem lastVisibleHeaderItem; GetVisibleHeaderItemRange(out firstVisibleHeaderItem, out lastVisibleHeaderItem); if (firstVisibleHeaderItem != null && firstVisibleHeaderItem._item > headerItem._item) { // Scroll backward. pixels = (int)(headerItem.BoundingRectangle.Left - firstVisibleHeaderItem.BoundingRectangle.Left); columns = headerItem._item - firstVisibleHeaderItem._item; } else if (lastVisibleHeaderItem != null && headerItem._item > lastVisibleHeaderItem._item) { // Scroll forward. pixels = (int)(headerItem.BoundingRectangle.Left - lastVisibleHeaderItem.BoundingRectangle.Left); columns = headerItem._item - lastVisibleHeaderItem._item; } int horizontalScrollAmount = 0; if (WindowsListView.IsListMode(hwndParent)) { // In list mode, LVM_SCROLL uses a column count. horizontalScrollAmount = columns; } else if (WindowsListView.IsDetailMode(hwndParent)) { // In details mode, LVM_SCROLL uses a pixel count. horizontalScrollAmount = pixels; } if (horizontalScrollAmount != 0) { Misc.ProxySendMessage(hwndParent, NativeMethods.LVM_SCROLL, new IntPtr(horizontalScrollAmount), IntPtr.Zero); } } } } private static bool HeaderIsHidden (IntPtr hwnd) { return Misc.IsBitSet(Misc.GetWindowStyle(hwnd), NativeMethods.HDS_HIDDEN); } // Map a header item static private int OrderToIndex (IntPtr hwnd, int order) { return Misc.ProxySendMessageInt(hwnd, NativeMethods.HDM_ORDERTOINDEX, new IntPtr(order), IntPtr.Zero); } // retrieve count of header items static private int HeaderItemCount (IntPtr hwnd) { return Misc.ProxySendMessageInt(hwnd, NativeMethods.HDM_GETITEMCOUNT, IntPtr.Zero, IntPtr.Zero); } private int GetItemFromIndex (int index) { NativeMethods.HDITEM item = new NativeMethods.HDITEM(); item.Init(); item.mask = NativeMethods.HDI_ORDER; // Send the message... if (!XSendMessage.GetItem(_hwnd, index, ref item)) { return -1; } return item.iOrder; } // Creates a header item private ProxySimple CreateHeaderItem (int index) { return new HeaderItem (_hwnd, this, index); } // Returns the number of elments in the Header private int Length { get { return HeaderItemCount (_hwnd); } } #endregion Private Methods //----------------------------------------------------- // // HeaderItem Private Class // //------------------------------------------------------ #region HeaderItem internal class HeaderItem: ProxyFragment, IInvokeProvider, IExpandCollapseProvider { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors internal HeaderItem (IntPtr hwnd, ProxyFragment parent, int item) : base( hwnd, parent, item ) { if (IsSplitButton()) { _cControlType = ControlType.SplitButton; } else { _cControlType = ControlType.HeaderItem; } // This string is a non-localizable string. _sAutomationId = "HeaderItem " + item.ToString(CultureInfo.InvariantCulture); _fIsContent = false; } #endregion Constructors //----------------------------------------------------- // // Patterns Implementation // //------------------------------------------------------ #region ProxySimple Interface // Returns a pattern interface if supported. internal override object GetPatternProvider (AutomationPattern iid) { if (RetrievePattern ()) { if (iid == InvokePattern.Pattern) { return (IsPushButton ()) ? this : null; } else if (iid == ExpandCollapsePattern.Pattern && IsSplitButton()) { return this; } } return null; } // Gets the bounding rectangle for this element internal override Rect BoundingRectangle { get { return BoundingRect().ToRect(Misc.IsControlRTL(_hwnd)); } } // Process all the Logical and Raw Element Properties internal override object GetElementProperty (AutomationProperty idProp) { if (idProp == AutomationElement.AccessKeyProperty) { return Misc.AccessKey(Text); } else if (idProp == AutomationElement.IsOffscreenProperty) { NativeMethods.Win32Rect itemRect = BoundingRect(); if (itemRect.IsEmpty) { return true; } // Need to check if this item is visible on the whole control not just its immediate parent. IntPtr hwndParent = Misc.GetParent(_hwnd); if (hwndParent != IntPtr.Zero) { NativeMethods.Win32Rect parentRect = NativeMethods.Win32Rect.Empty; if (Misc.GetClientRectInScreenCoordinates(hwndParent, ref parentRect) && !parentRect.IsEmpty) { if (!Misc.IsItemVisible(ref parentRect, ref itemRect)) { return true; } } } } return base.GetElementProperty (idProp); } // Gets the localized name internal override string LocalizedName { get { return Misc.StripMnemonic(Text); } } #endregion ProxySimple Interface #region Invoke Pattern // Same as a click on one of the header element void IInvokeProvider.Invoke () { // Make sure that the control is enabled if (!SafeNativeMethods.IsWindowEnabled(_hwnd)) { throw new ElementNotEnabledException(); } WindowsSysHeader parent = _parent as WindowsSysHeader; if (parent != null) { parent.ScrollIntoView(this); } NativeMethods.Win32Point pt; if (!GetInvokationPoint (out pt)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } IntPtr center = NativeMethods.Util.MAKELPARAM (pt.x, pt.y); // click Misc.ProxySendMessage(_hwnd, NativeMethods.WM_LBUTTONDOWN, new IntPtr(NativeMethods.MK_LBUTTON), center); Misc.ProxySendMessage(_hwnd, NativeMethods.WM_LBUTTONUP, IntPtr.Zero, center); } #endregion Invoke Pattern #region ExpandCollapse Pattern void IExpandCollapseProvider.Expand () { if (!IsExpanded()) { ClickSplitButton(); } } void IExpandCollapseProvider.Collapse () { if (IsExpanded()) { ClickSplitButton(); } } ExpandCollapseState IExpandCollapseProvider.ExpandCollapseState { get { if (IsExpanded()) { return ExpandCollapseState.Expanded; } return ExpandCollapseState.Collapsed; } } #endregion ExpandCollapse Pattern // This routine is only called on elements belonging to an hwnd that has the focus. protected override bool IsFocused () { if (Misc.IsComctrlV6OnOsVerV6orHigher(_hwnd)) { int item = Misc.ProxySendMessageInt(_hwnd, NativeMethods.HDM_GETFOCUSEDITEM, IntPtr.Zero, IntPtr.Zero); return item == _item; } return false; } //----------------------------------------------------- // // Private Methods // //------------------------------------------------------ #region Private Methods private string Text { get { // get index int index = OrderToIndex (_hwnd, _item); // new HDITEM to hold text // maximum size of 256 characters used here arbitrarily NativeMethods.HDITEM hdi = new NativeMethods.HDITEM(); hdi.Init(); hdi.mask = NativeMethods.HDI_TEXT; hdi.cchTextMax = 256; return XSendMessage.GetItemText(_hwnd, index, hdi); } } // 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; } // this method detects if header item // is in the state when it can be asked for the pattern private bool RetrievePattern () { if (!SafeNativeMethods.IsWindowEnabled (_hwnd) || !SafeNativeMethods.IsWindowVisible (_hwnd) || HeaderIsHidden (_hwnd)) { return false; } return true; } // header item looks and behaives like a push button private bool IsPushButton () { return (Misc.IsBitSet(WindowStyle, NativeMethods.HDS_BUTTONS)); } // header item looks and behaives like a push button private bool IsFilter () { return (Misc.IsBitSet(WindowStyle, NativeMethods.HDS_FILTERBAR)); } // retrieve a point which will invoke the // headeritem private bool GetInvokationPoint (out NativeMethods.Win32Point pt) { if (!GetClickablePoint(out pt, false)) { //If there is no clickable point, there is no use of calling MapWindowPoints return false; } // Map to client return Misc.MapWindowPoints(IntPtr.Zero, _hwnd, ref pt, 1); } // This is new with v6 comctrl on Vista private bool IsSplitButton () { NativeMethods.HDITEM item = new NativeMethods.HDITEM(); item.Init(); item.mask = NativeMethods.HDI_FORMAT; // Send the message... if (XSendMessage.GetItem(_hwnd, _item, ref item)) { if ((item.fmt & NativeMethods.HDF_SPLITBUTTON) != 0) { return true; } } return false; } // This is new with v6 comctrl on Vista private bool IsItemFocused () { int item = Misc.ProxySendMessageInt(_hwnd, NativeMethods.HDM_GETFOCUSEDITEM, IntPtr.Zero, IntPtr.Zero); if (item == _item) { return true; } return false; } // This is new with v6 comctrl on Vista private void ClickSplitButton () { // Make sure that the control is enabled if (!SafeNativeMethods.IsWindowEnabled(_hwnd)) { throw new ElementNotEnabledException(); } WindowsSysHeader parent = _parent as WindowsSysHeader; if (parent != null) { parent.ScrollIntoView(this); } Rect rect = XSendMessage.GetItemRect(_hwnd, NativeMethods.HDM_GETITEMDROPDOWNRECT, _item); NativeMethods.Win32Rect rectW32 = new NativeMethods.Win32Rect(rect); IntPtr center = NativeMethods.Util.MAKELPARAM (rectW32.left + ((rectW32.right - rectW32.left) / 2), rectW32.top + ((rectW32.bottom - rectW32.top) / 2)); // click // This code does not seem to work Misc.ProxySendMessage(_hwnd, NativeMethods.WM_LBUTTONDOWN, new IntPtr(NativeMethods.MK_LBUTTON), center); Misc.ProxySendMessage(_hwnd, NativeMethods.WM_LBUTTONUP, IntPtr.Zero, center); } #endregion Private Methods private bool IsExpanded() { // if the header has focus and the headitem has focus and we can find the dropdown window // then it must be accociated the this item because only on of these can exist at a time. if (Misc.GetFocusedWindow().Equals(_hwnd)) { // if this window does not exist it can't be expaned because this is the dropdown window. IntPtr hwndDropDown = Misc.FindWindowEx(IntPtr.Zero, IntPtr.Zero, "DropDown", null); if (hwndDropDown != IntPtr.Zero) { if (IsItemFocused()) { return true; } } } return false; } #endregion } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: Win32 SysHeader32 proxy // // History: // Jean-Francois Peyroux, alexsn - Created (in DotNet) // 2003/08/08 - alexsn Updated for WCP // // //--------------------------------------------------------------------------- using System; using System.Collections; using System.Globalization; using System.Runtime.InteropServices; using System.ComponentModel; using System.Text; using System.Windows.Automation; using System.Windows.Automation.Provider; using System.Windows; using System.Diagnostics; using MS.Win32; namespace MS.Internal.AutomationProxies { // Windows SysHeader32 proxy // NOTE: Since this proxy has its own HWND, it will be always discovered by UIAutomation // and placed where it should be // we MUST NEVER create a hard connection between us and header (via _parent) ourselves class WindowsSysHeader: ProxyHwnd { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors internal WindowsSysHeader (IntPtr hwnd) : base( hwnd, null, 0) { _cControlType = ControlType.Header; _fIsContent = false; _sAutomationId = "Header"; // This string is a non-localizable string // support for events _createOnEvent = new WinEventTracker.ProxyRaiseEvents (RaiseEvents); } #endregion Constructors #region Proxy Create // Static Create method called by UIAutomation to create this proxy. // returns null if unsuccessful internal static IRawElementProviderSimple Create(IntPtr hwnd, int idChild, int idObject) { return Create(hwnd, idChild); } internal static IRawElementProviderSimple Create(IntPtr hwnd, int idChild) { WindowsSysHeader header = new WindowsSysHeader(hwnd); if (idChild != 0) { return header.CreateHeaderItem(idChild - 1); } return header; } internal static void RaiseEvents (IntPtr hwnd, int eventId, object idProp, int idObject, int idChild) { if (idObject != NativeMethods.OBJID_VSCROLL && idObject != NativeMethods.OBJID_HSCROLL) { ProxyFragment header = new WindowsSysHeader(hwnd); AutomationProperty property = idProp as AutomationProperty; if (property == TablePattern.ColumnHeadersProperty || property == TablePattern.RowHeadersProperty) { // Check if the parent is a ListView IntPtr hwndParent = UnsafeNativeMethods.GetAncestor (hwnd, NativeMethods.GA_PARENT); if (hwndParent != IntPtr.Zero) { if (Misc.GetClassName(hwndParent).IndexOf("SysListView32", StringComparison.Ordinal) >= 0) { // Notify the Listview that the header Change WindowsListView wlv = (WindowsListView) WindowsListView.Create (hwndParent, 0); if (wlv != null) { wlv.DispatchEvents (eventId, idProp, idObject, idChild); } } } } else { if (idProp == InvokePattern.InvokedEvent) { ProxySimple headerItem = new HeaderItem(hwnd, header, idChild); headerItem.DispatchEvents(eventId, idProp, idObject, idChild); } else { header.DispatchEvents(eventId, idProp, idObject, idChild); } } } } #endregion //------------------------------------------------------ // // Patterns Implementation // //----------------------------------------------------- #region ProxyFragment Interface // 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) { // Determine how many items are in the list view. int item = child._item; return item + 1 < Length ? CreateHeaderItem (item + 1) : null; } // Returns the previous sibling element in the raw hierarchy. // Peripheral controls have always negative values. // Returns null is no previous internal override ProxySimple GetPreviousSibling (ProxySimple child) { // If the index of the previous node would be out of range... int item = child._item; return item > 0 ? CreateHeaderItem (item - 1) : null; } // Returns the first child element in the raw hierarchy. internal override ProxySimple GetFirstChild () { return Length > 0 ? CreateHeaderItem (0) : null; } // Returns the last child element in the raw hierarchy. internal override ProxySimple GetLastChild () { int count = Length; return count > 0 ? CreateHeaderItem (count - 1) : null; } // Returns a Proxy element corresponding to the specified screen coordinates. internal override ProxySimple ElementProviderFromPoint (int x, int y) { NativeMethods.HDHITTESTINFO HitTestInfo = new NativeMethods.HDHITTESTINFO(); HitTestInfo.pt = new NativeMethods.Win32Point (x, y); int index = -1; if (Misc.MapWindowPoints(IntPtr.Zero, _hwnd, ref HitTestInfo.pt, 1)) { unsafe { index = XSendMessage.XSendGetIndex(_hwnd, NativeMethods.HDM_HITTEST, IntPtr.Zero, new IntPtr(&HitTestInfo), Marshal.SizeOf(HitTestInfo.GetType())); } } // make sure that hit-test happened on the header item itself if (index != -1 && (NativeMethods.HHT_ONHEADER == (HitTestInfo.flags & 0x000F))) { return CreateHeaderItem (GetItemFromIndex (index)); } return this; } // Returns an item corresponding to the focused element (if there is one), or null otherwise. internal override ProxySimple GetFocus () { int item = Misc.ProxySendMessageInt(_hwnd, NativeMethods.HDM_GETFOCUSEDITEM, IntPtr.Zero, IntPtr.Zero); if (item < Length) return CreateHeaderItem (item); return null; } #endregion ProxyFragment Interface #region ProxySimple Interface // Process all the Logical and Raw Element Properties internal override object GetElementProperty(AutomationProperty idProp) { if (idProp == AutomationElement.OrientationProperty) { return Misc.IsBitSet(WindowStyle, NativeMethods.HDS_VERT) ? OrientationType.Vertical : OrientationType.Horizontal; } return base.GetElementProperty(idProp); } //Gets the localized name internal override string LocalizedName { get { return ST.Get(STID.LocalizedNameWindowsSysHeader); } } #endregion ProxySimple Interface // ------------------------------------------------------ // // Private Methods // // ------------------------------------------------------ #region Private Methods private void GetVisibleHeaderItemRange( out HeaderItem firstVisibleHeaderItem, out HeaderItem lastVisibleHeaderItem) { firstVisibleHeaderItem = null; lastVisibleHeaderItem = null; for (HeaderItem headerItem = GetFirstChild() as HeaderItem; headerItem != null; headerItem = GetNextSibling(headerItem) as HeaderItem) { bool isOffscreen = (bool) headerItem.GetElementProperty(AutomationElement.IsOffscreenProperty); if (!isOffscreen) { // Header item is visible. if (firstVisibleHeaderItem == null) { firstVisibleHeaderItem = headerItem; } lastVisibleHeaderItem = headerItem; } } } // Scroll the specified headerItem horizontally into view. internal void ScrollIntoView(HeaderItem headerItem) { // Check if the parent is a ListView IntPtr hwndParent = UnsafeNativeMethods.GetAncestor (_hwnd, NativeMethods.GA_PARENT); if (hwndParent != IntPtr.Zero) { if (Misc.GetClassName(hwndParent).IndexOf("SysListView32", StringComparison.Ordinal) >= 0) { // Determine the number of pixels or columns to scroll horizontally. int pixels = 0; int columns = 0; // Get first and last visible header items. HeaderItem firstVisibleHeaderItem; HeaderItem lastVisibleHeaderItem; GetVisibleHeaderItemRange(out firstVisibleHeaderItem, out lastVisibleHeaderItem); if (firstVisibleHeaderItem != null && firstVisibleHeaderItem._item > headerItem._item) { // Scroll backward. pixels = (int)(headerItem.BoundingRectangle.Left - firstVisibleHeaderItem.BoundingRectangle.Left); columns = headerItem._item - firstVisibleHeaderItem._item; } else if (lastVisibleHeaderItem != null && headerItem._item > lastVisibleHeaderItem._item) { // Scroll forward. pixels = (int)(headerItem.BoundingRectangle.Left - lastVisibleHeaderItem.BoundingRectangle.Left); columns = headerItem._item - lastVisibleHeaderItem._item; } int horizontalScrollAmount = 0; if (WindowsListView.IsListMode(hwndParent)) { // In list mode, LVM_SCROLL uses a column count. horizontalScrollAmount = columns; } else if (WindowsListView.IsDetailMode(hwndParent)) { // In details mode, LVM_SCROLL uses a pixel count. horizontalScrollAmount = pixels; } if (horizontalScrollAmount != 0) { Misc.ProxySendMessage(hwndParent, NativeMethods.LVM_SCROLL, new IntPtr(horizontalScrollAmount), IntPtr.Zero); } } } } private static bool HeaderIsHidden (IntPtr hwnd) { return Misc.IsBitSet(Misc.GetWindowStyle(hwnd), NativeMethods.HDS_HIDDEN); } // Map a header item static private int OrderToIndex (IntPtr hwnd, int order) { return Misc.ProxySendMessageInt(hwnd, NativeMethods.HDM_ORDERTOINDEX, new IntPtr(order), IntPtr.Zero); } // retrieve count of header items static private int HeaderItemCount (IntPtr hwnd) { return Misc.ProxySendMessageInt(hwnd, NativeMethods.HDM_GETITEMCOUNT, IntPtr.Zero, IntPtr.Zero); } private int GetItemFromIndex (int index) { NativeMethods.HDITEM item = new NativeMethods.HDITEM(); item.Init(); item.mask = NativeMethods.HDI_ORDER; // Send the message... if (!XSendMessage.GetItem(_hwnd, index, ref item)) { return -1; } return item.iOrder; } // Creates a header item private ProxySimple CreateHeaderItem (int index) { return new HeaderItem (_hwnd, this, index); } // Returns the number of elments in the Header private int Length { get { return HeaderItemCount (_hwnd); } } #endregion Private Methods //----------------------------------------------------- // // HeaderItem Private Class // //------------------------------------------------------ #region HeaderItem internal class HeaderItem: ProxyFragment, IInvokeProvider, IExpandCollapseProvider { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors internal HeaderItem (IntPtr hwnd, ProxyFragment parent, int item) : base( hwnd, parent, item ) { if (IsSplitButton()) { _cControlType = ControlType.SplitButton; } else { _cControlType = ControlType.HeaderItem; } // This string is a non-localizable string. _sAutomationId = "HeaderItem " + item.ToString(CultureInfo.InvariantCulture); _fIsContent = false; } #endregion Constructors //----------------------------------------------------- // // Patterns Implementation // //------------------------------------------------------ #region ProxySimple Interface // Returns a pattern interface if supported. internal override object GetPatternProvider (AutomationPattern iid) { if (RetrievePattern ()) { if (iid == InvokePattern.Pattern) { return (IsPushButton ()) ? this : null; } else if (iid == ExpandCollapsePattern.Pattern && IsSplitButton()) { return this; } } return null; } // Gets the bounding rectangle for this element internal override Rect BoundingRectangle { get { return BoundingRect().ToRect(Misc.IsControlRTL(_hwnd)); } } // Process all the Logical and Raw Element Properties internal override object GetElementProperty (AutomationProperty idProp) { if (idProp == AutomationElement.AccessKeyProperty) { return Misc.AccessKey(Text); } else if (idProp == AutomationElement.IsOffscreenProperty) { NativeMethods.Win32Rect itemRect = BoundingRect(); if (itemRect.IsEmpty) { return true; } // Need to check if this item is visible on the whole control not just its immediate parent. IntPtr hwndParent = Misc.GetParent(_hwnd); if (hwndParent != IntPtr.Zero) { NativeMethods.Win32Rect parentRect = NativeMethods.Win32Rect.Empty; if (Misc.GetClientRectInScreenCoordinates(hwndParent, ref parentRect) && !parentRect.IsEmpty) { if (!Misc.IsItemVisible(ref parentRect, ref itemRect)) { return true; } } } } return base.GetElementProperty (idProp); } // Gets the localized name internal override string LocalizedName { get { return Misc.StripMnemonic(Text); } } #endregion ProxySimple Interface #region Invoke Pattern // Same as a click on one of the header element void IInvokeProvider.Invoke () { // Make sure that the control is enabled if (!SafeNativeMethods.IsWindowEnabled(_hwnd)) { throw new ElementNotEnabledException(); } WindowsSysHeader parent = _parent as WindowsSysHeader; if (parent != null) { parent.ScrollIntoView(this); } NativeMethods.Win32Point pt; if (!GetInvokationPoint (out pt)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } IntPtr center = NativeMethods.Util.MAKELPARAM (pt.x, pt.y); // click Misc.ProxySendMessage(_hwnd, NativeMethods.WM_LBUTTONDOWN, new IntPtr(NativeMethods.MK_LBUTTON), center); Misc.ProxySendMessage(_hwnd, NativeMethods.WM_LBUTTONUP, IntPtr.Zero, center); } #endregion Invoke Pattern #region ExpandCollapse Pattern void IExpandCollapseProvider.Expand () { if (!IsExpanded()) { ClickSplitButton(); } } void IExpandCollapseProvider.Collapse () { if (IsExpanded()) { ClickSplitButton(); } } ExpandCollapseState IExpandCollapseProvider.ExpandCollapseState { get { if (IsExpanded()) { return ExpandCollapseState.Expanded; } return ExpandCollapseState.Collapsed; } } #endregion ExpandCollapse Pattern // This routine is only called on elements belonging to an hwnd that has the focus. protected override bool IsFocused () { if (Misc.IsComctrlV6OnOsVerV6orHigher(_hwnd)) { int item = Misc.ProxySendMessageInt(_hwnd, NativeMethods.HDM_GETFOCUSEDITEM, IntPtr.Zero, IntPtr.Zero); return item == _item; } return false; } //----------------------------------------------------- // // Private Methods // //------------------------------------------------------ #region Private Methods private string Text { get { // get index int index = OrderToIndex (_hwnd, _item); // new HDITEM to hold text // maximum size of 256 characters used here arbitrarily NativeMethods.HDITEM hdi = new NativeMethods.HDITEM(); hdi.Init(); hdi.mask = NativeMethods.HDI_TEXT; hdi.cchTextMax = 256; return XSendMessage.GetItemText(_hwnd, index, hdi); } } // 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; } // this method detects if header item // is in the state when it can be asked for the pattern private bool RetrievePattern () { if (!SafeNativeMethods.IsWindowEnabled (_hwnd) || !SafeNativeMethods.IsWindowVisible (_hwnd) || HeaderIsHidden (_hwnd)) { return false; } return true; } // header item looks and behaives like a push button private bool IsPushButton () { return (Misc.IsBitSet(WindowStyle, NativeMethods.HDS_BUTTONS)); } // header item looks and behaives like a push button private bool IsFilter () { return (Misc.IsBitSet(WindowStyle, NativeMethods.HDS_FILTERBAR)); } // retrieve a point which will invoke the // headeritem private bool GetInvokationPoint (out NativeMethods.Win32Point pt) { if (!GetClickablePoint(out pt, false)) { //If there is no clickable point, there is no use of calling MapWindowPoints return false; } // Map to client return Misc.MapWindowPoints(IntPtr.Zero, _hwnd, ref pt, 1); } // This is new with v6 comctrl on Vista private bool IsSplitButton () { NativeMethods.HDITEM item = new NativeMethods.HDITEM(); item.Init(); item.mask = NativeMethods.HDI_FORMAT; // Send the message... if (XSendMessage.GetItem(_hwnd, _item, ref item)) { if ((item.fmt & NativeMethods.HDF_SPLITBUTTON) != 0) { return true; } } return false; } // This is new with v6 comctrl on Vista private bool IsItemFocused () { int item = Misc.ProxySendMessageInt(_hwnd, NativeMethods.HDM_GETFOCUSEDITEM, IntPtr.Zero, IntPtr.Zero); if (item == _item) { return true; } return false; } // This is new with v6 comctrl on Vista private void ClickSplitButton () { // Make sure that the control is enabled if (!SafeNativeMethods.IsWindowEnabled(_hwnd)) { throw new ElementNotEnabledException(); } WindowsSysHeader parent = _parent as WindowsSysHeader; if (parent != null) { parent.ScrollIntoView(this); } Rect rect = XSendMessage.GetItemRect(_hwnd, NativeMethods.HDM_GETITEMDROPDOWNRECT, _item); NativeMethods.Win32Rect rectW32 = new NativeMethods.Win32Rect(rect); IntPtr center = NativeMethods.Util.MAKELPARAM (rectW32.left + ((rectW32.right - rectW32.left) / 2), rectW32.top + ((rectW32.bottom - rectW32.top) / 2)); // click // This code does not seem to work Misc.ProxySendMessage(_hwnd, NativeMethods.WM_LBUTTONDOWN, new IntPtr(NativeMethods.MK_LBUTTON), center); Misc.ProxySendMessage(_hwnd, NativeMethods.WM_LBUTTONUP, IntPtr.Zero, center); } #endregion Private Methods private bool IsExpanded() { // if the header has focus and the headitem has focus and we can find the dropdown window // then it must be accociated the this item because only on of these can exist at a time. if (Misc.GetFocusedWindow().Equals(_hwnd)) { // if this window does not exist it can't be expaned because this is the dropdown window. IntPtr hwndDropDown = Misc.FindWindowEx(IntPtr.Zero, IntPtr.Zero, "DropDown", null); if (hwndDropDown != IntPtr.Zero) { if (IsItemFocused()) { return true; } } } return false; } #endregion } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Parsers.cs
- DoubleStorage.cs
- ProcessingInstructionAction.cs
- DocumentOrderQuery.cs
- GridViewRowCollection.cs
- CompositeCollection.cs
- XmlSchemaSimpleContentExtension.cs
- SqlInternalConnectionTds.cs
- ManipulationBoundaryFeedbackEventArgs.cs
- HttpPostedFile.cs
- ExceptionUtil.cs
- Propagator.ExtentPlaceholderCreator.cs
- EmbeddedMailObject.cs
- Viewport2DVisual3D.cs
- Double.cs
- ComboBoxDesigner.cs
- UInt64Storage.cs
- ArraySegment.cs
- ProcessInfo.cs
- AspNetHostingPermission.cs
- FrugalList.cs
- SystemResourceHost.cs
- CodeValidator.cs
- InputChannelBinder.cs
- CalendarDataBindingHandler.cs
- WebPartConnectionsEventArgs.cs
- XPathArrayIterator.cs
- XmlSchemaAnnotated.cs
- RandomNumberGenerator.cs
- WebBrowser.cs
- CacheDependency.cs
- KoreanCalendar.cs
- TabItem.cs
- PrincipalPermission.cs
- CurrentTimeZone.cs
- PointValueSerializer.cs
- RegexInterpreter.cs
- FloaterParagraph.cs
- StateDesigner.Layouts.cs
- ColorConvertedBitmapExtension.cs
- SessionParameter.cs
- FocusTracker.cs
- smtpconnection.cs
- WebPartDescription.cs
- ToolCreatedEventArgs.cs
- Options.cs
- QueryAsyncResult.cs
- SqlDependencyUtils.cs
- UnauthorizedAccessException.cs
- MediaEntryAttribute.cs
- CodeVariableDeclarationStatement.cs
- CompilationRelaxations.cs
- AsymmetricSignatureFormatter.cs
- ZeroOpNode.cs
- HostingPreferredMapPath.cs
- ValidatedControlConverter.cs
- PointLightBase.cs
- MessageFormatterConverter.cs
- PeerResolverSettings.cs
- DbMetaDataColumnNames.cs
- Transform3DCollection.cs
- UrlMappingCollection.cs
- DateTimePickerDesigner.cs
- ImageMap.cs
- PolicyValidationException.cs
- Base64Decoder.cs
- DbConnectionOptions.cs
- NoneExcludedImageIndexConverter.cs
- _DomainName.cs
- LostFocusEventManager.cs
- TagNameToTypeMapper.cs
- ByteAnimationUsingKeyFrames.cs
- WebPartMenu.cs
- NamespaceList.cs
- Slider.cs
- CommandHelpers.cs
- AffineTransform3D.cs
- FontCacheUtil.cs
- XmlReaderSettings.cs
- WindowShowOrOpenTracker.cs
- InterleavedZipPartStream.cs
- GifBitmapDecoder.cs
- XmlSchemaSimpleType.cs
- LoginUtil.cs
- ProtocolsConfigurationHandler.cs
- WCFModelStrings.Designer.cs
- GridViewCommandEventArgs.cs
- RunInstallerAttribute.cs
- HatchBrush.cs
- FontSourceCollection.cs
- MetadataCacheItem.cs
- ReachUIElementCollectionSerializer.cs
- BasePattern.cs
- EmbeddedMailObjectsCollection.cs
- RpcCryptoRequest.cs
- DelayedRegex.cs
- DataSourceSerializationException.cs
- AssociationType.cs
- DataGridSortCommandEventArgs.cs
- DataSourceCollectionBase.cs