Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / UIAutomation / Win32Providers / MS / Internal / AutomationProxies / WindowsScroll.cs / 1 / WindowsScroll.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: Generic implementation of the scroll pattern for // controls having scroll bars. // // History: // 07/01/2003 : a-jeanp Created //--------------------------------------------------------------------------- using System; using System.ComponentModel; using System.Globalization; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Automation; using System.Windows.Automation.Provider; using MS.Win32; namespace MS.Internal.AutomationProxies { // Static class used to support the Scroll pattern for controls that have scroll bars. static class WindowScroll { #region Internal Methods // ----------------------------------------------------- // // Internal Methods // // ----------------------------------------------------- // Request to scroll Horizontally and vertically by the specified amount static internal void SetScrollPercent (IntPtr hwnd, double horizontalPercent, double verticalPercent, bool forceResults) { if (!IsScrollable(hwnd)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } bool resultsNoCheck; bool isHorizontal = SetScrollPercent (hwnd, horizontalPercent, NativeMethods.SB_HORZ, out resultsNoCheck); // This is needed for Controls that do not return the proper return codes to WinAPI Calls if (!isHorizontal && (forceResults && resultsNoCheck)) { isHorizontal = true; } bool isVertical = SetScrollPercent (hwnd, verticalPercent, NativeMethods.SB_VERT, out resultsNoCheck); // This is needed for Controls that do not return the proper return codes to WinAPI Calls if (!isVertical && (forceResults && resultsNoCheck)) { isVertical = true; } if (isHorizontal && isVertical) { return; } throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } // Request to scroll horizontally and vertically by the specified scrolling amount static internal void Scroll (IntPtr hwnd, ScrollAmount HorizontalAmount, ScrollAmount VerticalAmount, bool fForceResults) { if (!IsScrollable(hwnd)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } bool fHz = ScrollCursor(hwnd, HorizontalAmount, NativeMethods.SB_HORZ, fForceResults); bool fVt = ScrollCursor (hwnd, VerticalAmount, NativeMethods.SB_VERT, fForceResults); if ( fHz && fVt ) return; throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } // Process the Scroll Properties static internal object GetPropertyScroll (AutomationProperty idProp, IntPtr hwnd) { // ...handle the scroll properties... if (idProp == ScrollPattern.HorizontalScrollPercentProperty) { return Scrollable (hwnd, NativeMethods.SB_HORZ) ? GetScrollInfo (hwnd, NativeMethods.SB_HORZ) : ScrollPattern.NoScroll; } else if (idProp == ScrollPattern.VerticalScrollPercentProperty) { return Scrollable (hwnd, NativeMethods.SB_VERT) ? GetScrollInfo (hwnd, NativeMethods.SB_VERT) : ScrollPattern.NoScroll; } else if (idProp == ScrollPattern.HorizontalViewSizeProperty) { return Scrollable (hwnd, NativeMethods.SB_HORZ) ? ScrollViewSize (hwnd, NativeMethods.SB_HORZ) : 100.0; } else if (idProp == ScrollPattern.VerticalViewSizeProperty) { return Scrollable (hwnd, NativeMethods.SB_VERT) ? ScrollViewSize (hwnd, NativeMethods.SB_VERT) : 100.0; } else if (idProp == ScrollPattern.HorizontallyScrollableProperty) { return Scrollable (hwnd, NativeMethods.SB_HORZ); } else if (idProp == ScrollPattern.VerticallyScrollableProperty) { return Scrollable (hwnd, NativeMethods.SB_VERT); } return null; } // Finds if a control can be scrolled static internal bool Scrollable (IntPtr hwnd, int sbFlag) { int style = Misc.GetWindowStyle(hwnd); if ((sbFlag == NativeMethods.SB_HORZ && !Misc.IsBitSet(style, NativeMethods.WS_HSCROLL)) || (sbFlag == NativeMethods.SB_VERT && !Misc.IsBitSet(style, NativeMethods.WS_VSCROLL))) { return false; } if (!Misc.IsEnabled(hwnd)) { return false; } // Check if the scroll info shows the scroll bar as enabled. bool scrollBarEnabled = false; NativeMethods.ScrollBarInfo sbi = new NativeMethods.ScrollBarInfo(); sbi.cbSize = Marshal.SizeOf(sbi.GetType()); int scrollBarObjectId = (sbFlag == NativeMethods.SB_VERT) ? NativeMethods.OBJID_VSCROLL : NativeMethods.OBJID_HSCROLL; if (Misc.GetScrollBarInfo(hwnd, scrollBarObjectId, ref sbi)) { scrollBarEnabled = !Misc.IsBitSet(sbi.scrollBarInfo, NativeMethods.STATE_SYSTEM_UNAVAILABLE); } if (!scrollBarEnabled) { return false; } // Get scroll range NativeMethods.ScrollInfo si = new NativeMethods.ScrollInfo (); si.cbSize = Marshal.SizeOf (si.GetType ()); si.fMask = NativeMethods.SIF_ALL; if (!Misc.GetScrollInfo(hwnd, sbFlag, ref si)) { return false; } return (si.nMax != si.nMin && si.nPage != si.nMax - si.nMin + 1); } static internal bool HasScrollableStyle(IntPtr hwnd) { int style = Misc.GetWindowStyle(hwnd); bool hasScrollableStyle = Misc.IsBitSet(style, NativeMethods.WS_HSCROLL) || Misc.IsBitSet(style, NativeMethods.WS_VSCROLL); string className = Misc.ProxyGetClassName(hwnd); if (className.StartsWith("RichEdit", StringComparison.OrdinalIgnoreCase) || className.StartsWith("WindowForms10.RichEdit", StringComparison.OrdinalIgnoreCase) || string.Compare(className, "Edit", StringComparison.OrdinalIgnoreCase) == 0) { hasScrollableStyle = Misc.IsBitSet(style, NativeMethods.ES_MULTILINE); } return hasScrollableStyle; } // Finds if a control can be scrolled static internal bool IsScrollable(IntPtr hwnd) { return Scrollable(hwnd, NativeMethods.SB_HORZ) || Scrollable(hwnd, NativeMethods.SB_VERT); } #endregion #region Private Methods // ------------------------------------------------------ // // Private Methods // // ----------------------------------------------------- // Retrieve the scrollbar position in the [0..100]% range static private double GetScrollInfo(IntPtr hwnd, int sbFlag) { // check if there is a scrollbar NativeMethods.ScrollInfo si = new NativeMethods.ScrollInfo (); si.fMask = NativeMethods.SIF_ALL; si.cbSize = Marshal.SizeOf (si.GetType ()); if (Misc.GetScrollInfo(hwnd, sbFlag, ref si)) { if (si.nMax != si.nMin && si.nPage != si.nMax - si.nMin + 1) { int delta; // NOTE: // Proportional scrollbars have a few key values: min, max, page, and current. // // Min and max represent the endpoints of the scrollbar; page is the side of the thumb, // and current is the position of the leading edge of the thumb (top for a vert scrollbar). // // Because of this arrangment, current can't be any value between min and max, it's actually // confied to min...(max-page)+1. That +1 is a quirk of the scrollbar's internal logic. // // For example, in an edit in notepad, these might be: // min = 0 // max = 33 (~total lines in file) // current = { any value from 0 .. 12 inclusive } // page = 22 // // Most controls just let the scrollbar do all the proportional logic: they pass the incoming // values from the scroll messages (eg as a reuslt of dragging with a mouse or from UIA's SetValue) // straight down to the scrollbar APIs. // // RichEdit is different: it does its own extra 'validation', and limits the current value to // (max-page) - without that +1. // // The end result of this is that it's not possible using UIA to scroll a richedit to the max value: // the richedit is exposing (implicitly through the scrollbar APIs) a max value one higher than the // max value that it will actually allow. string classname = Misc.GetClassName(hwnd); if (classname.ToLower(System.Globalization.CultureInfo.InvariantCulture).Contains("richedit")) { delta = (si.nPage > 0) ? si.nPage : 0; } else { delta = (si.nPage > 0) ? si.nPage - 1 : 0; } return 100.0 * (si.nPos - si.nMin) / ((si.nMax - delta) - si.nMin); } } return (double)ScrollPattern.NoScroll; } // View Size static private double ScrollViewSize(IntPtr hwnd, int sbFlag) { // Get scroll range and page size NativeMethods.ScrollInfo si = new NativeMethods.ScrollInfo (); si.cbSize = Marshal.SizeOf (si.GetType ()); si.fMask = NativeMethods.SIF_RANGE | NativeMethods.SIF_PAGE; if (!Misc.GetScrollInfo(hwnd, sbFlag, ref si) || (si.nMax == si.nMin)) { return 100.0; } else { // "+1" because nPage can be 0 to nMax-nMin+1 int nPage = si.nPage > 0 ? si.nPage : 1; return (100.0 * nPage) / (si.nMax + 1 - si.nMin); } } // Request to scroll a control horizontally or vertically by a specified amount. static private bool SetScrollPercent(IntPtr hwnd, double fScrollPos, int sbFlag, out bool forceResults) { forceResults = false; // Check param if ((int)fScrollPos == (int)ScrollPattern.NoScroll) { return true; } if (!Scrollable(hwnd, sbFlag)) { return false; } if (fScrollPos < 0 || fScrollPos > 100) { throw new ArgumentOutOfRangeException(sbFlag == NativeMethods.SB_HORZ ? "horizontalPercent" : "verticalPercent", SR.Get(SRID.ScrollBarOutOfRange)); } // Get Max & min NativeMethods.ScrollInfo si = new NativeMethods.ScrollInfo (); si.fMask = NativeMethods.SIF_ALL; si.cbSize = Marshal.SizeOf(si.GetType ()); // if no scroll bar return false // on Win 6.0 success is false // on other system check through the scroll info is a scroll bar is there if (!Misc.GetScrollInfo(hwnd, sbFlag, ref si) || !((si.nMax != si.nMin && si.nPage != si.nMax - si.nMin + 1))) { return false; } // Set position int delta = (si.nPage > 0) ? si.nPage - 1 : 0; int newPos = (int) Math.Round (((si.nMax - delta) - si.nMin) * fScrollPos / 100.0 + si.nMin); // No move, exit if (newPos == si.nPos) { return true; } si.nPos = newPos; forceResults = true; int message = sbFlag == NativeMethods.SB_HORZ ? NativeMethods.WM_HSCROLL : NativeMethods.WM_VSCROLL; int wParam = NativeMethods.Util.MAKELONG(NativeMethods.SB_THUMBPOSITION, si.nPos); bool fRet = Misc.ProxySendMessageInt(hwnd, message, (IntPtr)wParam, IntPtr.Zero) == 0; if (fRet && Misc.GetScrollInfo(hwnd, sbFlag, ref si) && si.nPos != newPos) { // WinForms treeview has some problems. The first is that the SendMessage with WM_HSCROLL/WM_VSCROLL // with SB_THUMBPOSITION is not moving the scroll position. The second problem is that SetScrollInfo() // lose the theming for the scroll bars and it really does not move the scroll position. The // scrollbars change but it does not scroll the treeview control. int prevPos = newPos; ScrollAmount prevAmount = si.nPos > newPos ? ScrollAmount.SmallDecrement : ScrollAmount.SmallIncrement; do { ScrollAmount amount = si.nPos > newPos ? ScrollAmount.SmallDecrement : ScrollAmount.SmallIncrement; // If we were moving in one direction and overshoot, break to prevent getting into infant loop. // If ScrollCursor() can not set the new position, also break to prevent infant loop. if (prevAmount != amount || prevPos == si.nPos) { break; } prevPos = si.nPos; fRet = ScrollCursor(hwnd, amount, sbFlag, forceResults); } while (fRet && Misc.GetScrollInfo(hwnd, sbFlag, ref si) && si.nPos != newPos); } return fRet; } // Scroll control by a given amount static private bool ScrollCursor(IntPtr hwnd, ScrollAmount amount, int sbFlag, bool fForceResults) { // Check Param if (amount == ScrollAmount.NoAmount) { return true; } if (!Scrollable(hwnd, sbFlag)) { return false; } // Get Max & min NativeMethods.ScrollInfo si = new NativeMethods.ScrollInfo (); si.fMask = NativeMethods.SIF_ALL; si.cbSize = Marshal.SizeOf (si.GetType ()); // if no scroll bar return false // on Win 6.0 success is false // on other system check through the scroll info is a scroll bar is there if ((!Misc.GetScrollInfo(hwnd, sbFlag, ref si) || !((si.nMax != si.nMin && si.nPage != si.nMax - si.nMin + 1)))) { return false; } // Get Action to perform int nAction; if (sbFlag == NativeMethods.SB_HORZ) { switch (amount) { case ScrollAmount.SmallDecrement : nAction = NativeMethods.SB_LINELEFT; break; case ScrollAmount.LargeDecrement : nAction = NativeMethods.SB_PAGELEFT; break; case ScrollAmount.SmallIncrement : nAction = NativeMethods.SB_LINERIGHT; break; case ScrollAmount.LargeIncrement : nAction = NativeMethods.SB_PAGERIGHT; break; default : return false; } } else { switch (amount) { case ScrollAmount.SmallDecrement : nAction = NativeMethods.SB_LINEUP; break; case ScrollAmount.LargeDecrement : nAction = NativeMethods.SB_PAGEUP; break; case ScrollAmount.SmallIncrement : nAction = NativeMethods.SB_LINEDOWN; break; case ScrollAmount.LargeIncrement : nAction = NativeMethods.SB_PAGEDOWN; break; default : return false; } } // Set position int wParam = NativeMethods.Util.MAKELONG (nAction, 0); int message = sbFlag == NativeMethods.SB_HORZ ? NativeMethods.WM_HSCROLL : NativeMethods.WM_VSCROLL; int result = Misc.ProxySendMessageInt(hwnd, message, (IntPtr)wParam, IntPtr.Zero); return result == 0 || fForceResults; } #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: Generic implementation of the scroll pattern for // controls having scroll bars. // // History: // 07/01/2003 : a-jeanp Created //--------------------------------------------------------------------------- using System; using System.ComponentModel; using System.Globalization; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Automation; using System.Windows.Automation.Provider; using MS.Win32; namespace MS.Internal.AutomationProxies { // Static class used to support the Scroll pattern for controls that have scroll bars. static class WindowScroll { #region Internal Methods // ----------------------------------------------------- // // Internal Methods // // ----------------------------------------------------- // Request to scroll Horizontally and vertically by the specified amount static internal void SetScrollPercent (IntPtr hwnd, double horizontalPercent, double verticalPercent, bool forceResults) { if (!IsScrollable(hwnd)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } bool resultsNoCheck; bool isHorizontal = SetScrollPercent (hwnd, horizontalPercent, NativeMethods.SB_HORZ, out resultsNoCheck); // This is needed for Controls that do not return the proper return codes to WinAPI Calls if (!isHorizontal && (forceResults && resultsNoCheck)) { isHorizontal = true; } bool isVertical = SetScrollPercent (hwnd, verticalPercent, NativeMethods.SB_VERT, out resultsNoCheck); // This is needed for Controls that do not return the proper return codes to WinAPI Calls if (!isVertical && (forceResults && resultsNoCheck)) { isVertical = true; } if (isHorizontal && isVertical) { return; } throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } // Request to scroll horizontally and vertically by the specified scrolling amount static internal void Scroll (IntPtr hwnd, ScrollAmount HorizontalAmount, ScrollAmount VerticalAmount, bool fForceResults) { if (!IsScrollable(hwnd)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } bool fHz = ScrollCursor(hwnd, HorizontalAmount, NativeMethods.SB_HORZ, fForceResults); bool fVt = ScrollCursor (hwnd, VerticalAmount, NativeMethods.SB_VERT, fForceResults); if ( fHz && fVt ) return; throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } // Process the Scroll Properties static internal object GetPropertyScroll (AutomationProperty idProp, IntPtr hwnd) { // ...handle the scroll properties... if (idProp == ScrollPattern.HorizontalScrollPercentProperty) { return Scrollable (hwnd, NativeMethods.SB_HORZ) ? GetScrollInfo (hwnd, NativeMethods.SB_HORZ) : ScrollPattern.NoScroll; } else if (idProp == ScrollPattern.VerticalScrollPercentProperty) { return Scrollable (hwnd, NativeMethods.SB_VERT) ? GetScrollInfo (hwnd, NativeMethods.SB_VERT) : ScrollPattern.NoScroll; } else if (idProp == ScrollPattern.HorizontalViewSizeProperty) { return Scrollable (hwnd, NativeMethods.SB_HORZ) ? ScrollViewSize (hwnd, NativeMethods.SB_HORZ) : 100.0; } else if (idProp == ScrollPattern.VerticalViewSizeProperty) { return Scrollable (hwnd, NativeMethods.SB_VERT) ? ScrollViewSize (hwnd, NativeMethods.SB_VERT) : 100.0; } else if (idProp == ScrollPattern.HorizontallyScrollableProperty) { return Scrollable (hwnd, NativeMethods.SB_HORZ); } else if (idProp == ScrollPattern.VerticallyScrollableProperty) { return Scrollable (hwnd, NativeMethods.SB_VERT); } return null; } // Finds if a control can be scrolled static internal bool Scrollable (IntPtr hwnd, int sbFlag) { int style = Misc.GetWindowStyle(hwnd); if ((sbFlag == NativeMethods.SB_HORZ && !Misc.IsBitSet(style, NativeMethods.WS_HSCROLL)) || (sbFlag == NativeMethods.SB_VERT && !Misc.IsBitSet(style, NativeMethods.WS_VSCROLL))) { return false; } if (!Misc.IsEnabled(hwnd)) { return false; } // Check if the scroll info shows the scroll bar as enabled. bool scrollBarEnabled = false; NativeMethods.ScrollBarInfo sbi = new NativeMethods.ScrollBarInfo(); sbi.cbSize = Marshal.SizeOf(sbi.GetType()); int scrollBarObjectId = (sbFlag == NativeMethods.SB_VERT) ? NativeMethods.OBJID_VSCROLL : NativeMethods.OBJID_HSCROLL; if (Misc.GetScrollBarInfo(hwnd, scrollBarObjectId, ref sbi)) { scrollBarEnabled = !Misc.IsBitSet(sbi.scrollBarInfo, NativeMethods.STATE_SYSTEM_UNAVAILABLE); } if (!scrollBarEnabled) { return false; } // Get scroll range NativeMethods.ScrollInfo si = new NativeMethods.ScrollInfo (); si.cbSize = Marshal.SizeOf (si.GetType ()); si.fMask = NativeMethods.SIF_ALL; if (!Misc.GetScrollInfo(hwnd, sbFlag, ref si)) { return false; } return (si.nMax != si.nMin && si.nPage != si.nMax - si.nMin + 1); } static internal bool HasScrollableStyle(IntPtr hwnd) { int style = Misc.GetWindowStyle(hwnd); bool hasScrollableStyle = Misc.IsBitSet(style, NativeMethods.WS_HSCROLL) || Misc.IsBitSet(style, NativeMethods.WS_VSCROLL); string className = Misc.ProxyGetClassName(hwnd); if (className.StartsWith("RichEdit", StringComparison.OrdinalIgnoreCase) || className.StartsWith("WindowForms10.RichEdit", StringComparison.OrdinalIgnoreCase) || string.Compare(className, "Edit", StringComparison.OrdinalIgnoreCase) == 0) { hasScrollableStyle = Misc.IsBitSet(style, NativeMethods.ES_MULTILINE); } return hasScrollableStyle; } // Finds if a control can be scrolled static internal bool IsScrollable(IntPtr hwnd) { return Scrollable(hwnd, NativeMethods.SB_HORZ) || Scrollable(hwnd, NativeMethods.SB_VERT); } #endregion #region Private Methods // ------------------------------------------------------ // // Private Methods // // ----------------------------------------------------- // Retrieve the scrollbar position in the [0..100]% range static private double GetScrollInfo(IntPtr hwnd, int sbFlag) { // check if there is a scrollbar NativeMethods.ScrollInfo si = new NativeMethods.ScrollInfo (); si.fMask = NativeMethods.SIF_ALL; si.cbSize = Marshal.SizeOf (si.GetType ()); if (Misc.GetScrollInfo(hwnd, sbFlag, ref si)) { if (si.nMax != si.nMin && si.nPage != si.nMax - si.nMin + 1) { int delta; // NOTE: // Proportional scrollbars have a few key values: min, max, page, and current. // // Min and max represent the endpoints of the scrollbar; page is the side of the thumb, // and current is the position of the leading edge of the thumb (top for a vert scrollbar). // // Because of this arrangment, current can't be any value between min and max, it's actually // confied to min...(max-page)+1. That +1 is a quirk of the scrollbar's internal logic. // // For example, in an edit in notepad, these might be: // min = 0 // max = 33 (~total lines in file) // current = { any value from 0 .. 12 inclusive } // page = 22 // // Most controls just let the scrollbar do all the proportional logic: they pass the incoming // values from the scroll messages (eg as a reuslt of dragging with a mouse or from UIA's SetValue) // straight down to the scrollbar APIs. // // RichEdit is different: it does its own extra 'validation', and limits the current value to // (max-page) - without that +1. // // The end result of this is that it's not possible using UIA to scroll a richedit to the max value: // the richedit is exposing (implicitly through the scrollbar APIs) a max value one higher than the // max value that it will actually allow. string classname = Misc.GetClassName(hwnd); if (classname.ToLower(System.Globalization.CultureInfo.InvariantCulture).Contains("richedit")) { delta = (si.nPage > 0) ? si.nPage : 0; } else { delta = (si.nPage > 0) ? si.nPage - 1 : 0; } return 100.0 * (si.nPos - si.nMin) / ((si.nMax - delta) - si.nMin); } } return (double)ScrollPattern.NoScroll; } // View Size static private double ScrollViewSize(IntPtr hwnd, int sbFlag) { // Get scroll range and page size NativeMethods.ScrollInfo si = new NativeMethods.ScrollInfo (); si.cbSize = Marshal.SizeOf (si.GetType ()); si.fMask = NativeMethods.SIF_RANGE | NativeMethods.SIF_PAGE; if (!Misc.GetScrollInfo(hwnd, sbFlag, ref si) || (si.nMax == si.nMin)) { return 100.0; } else { // "+1" because nPage can be 0 to nMax-nMin+1 int nPage = si.nPage > 0 ? si.nPage : 1; return (100.0 * nPage) / (si.nMax + 1 - si.nMin); } } // Request to scroll a control horizontally or vertically by a specified amount. static private bool SetScrollPercent(IntPtr hwnd, double fScrollPos, int sbFlag, out bool forceResults) { forceResults = false; // Check param if ((int)fScrollPos == (int)ScrollPattern.NoScroll) { return true; } if (!Scrollable(hwnd, sbFlag)) { return false; } if (fScrollPos < 0 || fScrollPos > 100) { throw new ArgumentOutOfRangeException(sbFlag == NativeMethods.SB_HORZ ? "horizontalPercent" : "verticalPercent", SR.Get(SRID.ScrollBarOutOfRange)); } // Get Max & min NativeMethods.ScrollInfo si = new NativeMethods.ScrollInfo (); si.fMask = NativeMethods.SIF_ALL; si.cbSize = Marshal.SizeOf(si.GetType ()); // if no scroll bar return false // on Win 6.0 success is false // on other system check through the scroll info is a scroll bar is there if (!Misc.GetScrollInfo(hwnd, sbFlag, ref si) || !((si.nMax != si.nMin && si.nPage != si.nMax - si.nMin + 1))) { return false; } // Set position int delta = (si.nPage > 0) ? si.nPage - 1 : 0; int newPos = (int) Math.Round (((si.nMax - delta) - si.nMin) * fScrollPos / 100.0 + si.nMin); // No move, exit if (newPos == si.nPos) { return true; } si.nPos = newPos; forceResults = true; int message = sbFlag == NativeMethods.SB_HORZ ? NativeMethods.WM_HSCROLL : NativeMethods.WM_VSCROLL; int wParam = NativeMethods.Util.MAKELONG(NativeMethods.SB_THUMBPOSITION, si.nPos); bool fRet = Misc.ProxySendMessageInt(hwnd, message, (IntPtr)wParam, IntPtr.Zero) == 0; if (fRet && Misc.GetScrollInfo(hwnd, sbFlag, ref si) && si.nPos != newPos) { // WinForms treeview has some problems. The first is that the SendMessage with WM_HSCROLL/WM_VSCROLL // with SB_THUMBPOSITION is not moving the scroll position. The second problem is that SetScrollInfo() // lose the theming for the scroll bars and it really does not move the scroll position. The // scrollbars change but it does not scroll the treeview control. int prevPos = newPos; ScrollAmount prevAmount = si.nPos > newPos ? ScrollAmount.SmallDecrement : ScrollAmount.SmallIncrement; do { ScrollAmount amount = si.nPos > newPos ? ScrollAmount.SmallDecrement : ScrollAmount.SmallIncrement; // If we were moving in one direction and overshoot, break to prevent getting into infant loop. // If ScrollCursor() can not set the new position, also break to prevent infant loop. if (prevAmount != amount || prevPos == si.nPos) { break; } prevPos = si.nPos; fRet = ScrollCursor(hwnd, amount, sbFlag, forceResults); } while (fRet && Misc.GetScrollInfo(hwnd, sbFlag, ref si) && si.nPos != newPos); } return fRet; } // Scroll control by a given amount static private bool ScrollCursor(IntPtr hwnd, ScrollAmount amount, int sbFlag, bool fForceResults) { // Check Param if (amount == ScrollAmount.NoAmount) { return true; } if (!Scrollable(hwnd, sbFlag)) { return false; } // Get Max & min NativeMethods.ScrollInfo si = new NativeMethods.ScrollInfo (); si.fMask = NativeMethods.SIF_ALL; si.cbSize = Marshal.SizeOf (si.GetType ()); // if no scroll bar return false // on Win 6.0 success is false // on other system check through the scroll info is a scroll bar is there if ((!Misc.GetScrollInfo(hwnd, sbFlag, ref si) || !((si.nMax != si.nMin && si.nPage != si.nMax - si.nMin + 1)))) { return false; } // Get Action to perform int nAction; if (sbFlag == NativeMethods.SB_HORZ) { switch (amount) { case ScrollAmount.SmallDecrement : nAction = NativeMethods.SB_LINELEFT; break; case ScrollAmount.LargeDecrement : nAction = NativeMethods.SB_PAGELEFT; break; case ScrollAmount.SmallIncrement : nAction = NativeMethods.SB_LINERIGHT; break; case ScrollAmount.LargeIncrement : nAction = NativeMethods.SB_PAGERIGHT; break; default : return false; } } else { switch (amount) { case ScrollAmount.SmallDecrement : nAction = NativeMethods.SB_LINEUP; break; case ScrollAmount.LargeDecrement : nAction = NativeMethods.SB_PAGEUP; break; case ScrollAmount.SmallIncrement : nAction = NativeMethods.SB_LINEDOWN; break; case ScrollAmount.LargeIncrement : nAction = NativeMethods.SB_PAGEDOWN; break; default : return false; } } // Set position int wParam = NativeMethods.Util.MAKELONG (nAction, 0); int message = sbFlag == NativeMethods.SB_HORZ ? NativeMethods.WM_HSCROLL : NativeMethods.WM_VSCROLL; int result = Misc.ProxySendMessageInt(hwnd, message, (IntPtr)wParam, IntPtr.Zero); return result == 0 || fForceResults; } #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
- TextBoxBase.cs
- BufferBuilder.cs
- XmlSchemaType.cs
- InteropBitmapSource.cs
- PlaceHolder.cs
- HttpInputStream.cs
- WebPartsSection.cs
- FixedHighlight.cs
- StringToken.cs
- MetadataArtifactLoaderFile.cs
- WmlLinkAdapter.cs
- TypedTableBaseExtensions.cs
- __FastResourceComparer.cs
- WsdlServiceChannelBuilder.cs
- X509ThumbprintKeyIdentifierClause.cs
- AsyncResult.cs
- RepeaterCommandEventArgs.cs
- TemplateBindingExpressionConverter.cs
- VirtualizedItemPattern.cs
- ValueOfAction.cs
- ProtectedProviderSettings.cs
- InheritedPropertyDescriptor.cs
- ObjectDataSourceMethodEventArgs.cs
- WindowsFormsSectionHandler.cs
- HwndAppCommandInputProvider.cs
- PartManifestEntry.cs
- DataGridViewRowsRemovedEventArgs.cs
- ExtendedTransformFactory.cs
- DbLambda.cs
- DefaultExpression.cs
- _UriTypeConverter.cs
- SkewTransform.cs
- Track.cs
- EntityDataSourceContextCreatedEventArgs.cs
- TargetPerspective.cs
- RSAOAEPKeyExchangeFormatter.cs
- IMembershipProvider.cs
- WebSysDisplayNameAttribute.cs
- PrimitiveCodeDomSerializer.cs
- HierarchicalDataBoundControlAdapter.cs
- ClientUIRequest.cs
- Ipv6Element.cs
- XMLDiffLoader.cs
- URLIdentityPermission.cs
- AsnEncodedData.cs
- CustomAttributeBuilder.cs
- PeerName.cs
- RadioButtonBaseAdapter.cs
- HScrollProperties.cs
- UpdateExpressionVisitor.cs
- SerialPort.cs
- XmlSchemaComplexContentExtension.cs
- Stroke2.cs
- XsltConvert.cs
- RecognizeCompletedEventArgs.cs
- FrameworkContentElement.cs
- SQLConvert.cs
- DateBoldEvent.cs
- ToolStripDropDownButton.cs
- ButtonChrome.cs
- ToolStripPanel.cs
- AuthorizationSection.cs
- EntityDataSourceColumn.cs
- OracleDataAdapter.cs
- PageBreakRecord.cs
- SmtpReplyReaderFactory.cs
- ScriptingScriptResourceHandlerSection.cs
- FileLoadException.cs
- CollectionView.cs
- CornerRadiusConverter.cs
- Baml2006SchemaContext.cs
- RoleGroupCollection.cs
- PagesSection.cs
- AmbiguousMatchException.cs
- SoapSchemaExporter.cs
- HtmlTitle.cs
- ObjectFullSpanRewriter.cs
- CodeAttributeArgument.cs
- MissingSatelliteAssemblyException.cs
- OleDragDropHandler.cs
- AsymmetricCryptoHandle.cs
- SqlDataSourceEnumerator.cs
- ProviderIncompatibleException.cs
- SecurityElement.cs
- SpotLight.cs
- GatewayIPAddressInformationCollection.cs
- CacheMemory.cs
- BehaviorEditorPart.cs
- ByteAnimation.cs
- InputManager.cs
- DependencyPropertyValueSerializer.cs
- ComIntegrationManifestGenerator.cs
- ApplicationHost.cs
- ButtonRenderer.cs
- ApplicationServicesHostFactory.cs
- RuntimeArgumentHandle.cs
- XPathDescendantIterator.cs
- WindowInteractionStateTracker.cs
- StorageFunctionMapping.cs
- SecurityTokenRequirement.cs