First of all, basically I believe I just need help in figuring out how to calculate it, math isnt really my strong side.
FYI, the MS-Word is most likely not relevant to solve my problem, I basically just mention it so you know the context I am in, but I believe it should be solvable also for people who have no knowledge about MS-Word.
I have the problem that Word has the property VerticalPercentScrolled
which is an integer
.
Which isnt as accurate as I need it to be, consider a Word Document with 300 pages and the scrollbar can only have a integer
between 0 - 100 (percent), so for example 25 percent of a 300 page document is a rather big range.
I have now gone and read the correct value, with the help of UI Automation
library - TestStack.White - and can successfully set it to its old value, if some un-desired scrolling happens.
Like this:
var hWnd = (IntPtr)WordUtils.GetHwnd();
var processId = Process.GetCurrentProcess().Id;
var uiApp = TestStack.White.Application.Attach((int)processId);
var uiWindow = uiApp.GetWindow(WindowHandling.GetWindowText(hWnd), InitializeOption.NoCache);
var wf = (IUIItemContainer)uiWindow.Get(SearchCriteria.ByClassName("_WwF"));
var wbs= wf.GetMultiple(SearchCriteria.ByClassName("_WwB"));
if (wbs.Length != 1)
return;
var wb= (IUIItemContainer)wbs.First();
var wgs = wb.GetMultiple(SearchCriteria.ByClassName("_WwG"));
if (wgs.Length != 1)
return;
var wg = wgs.First();
var element = wg.AutomationElement;
var oldVerticalPercent = (double)element.GetCurrentPropertyValue(ScrollPattern.VerticalScrollPercentProperty);
with this code I get a percent value of lets say 9.442248572683356
instead of 9
.
To reset the value I use the following code:
object scrollPattern;
if (element.TryGetCurrentPattern(ScrollPattern.Pattern, out scrollPattern))
((ScrollPattern)scrollPattern).SetScrollPercent(ScrollPattern.NoScroll, oldVerticalPercent);
This works like a charm.
Now my problem is what if my document gets larger/smaller during the time I stored the oldValue and want to reapply it, my oldValue needs to be adjusted.
I can read the following values (at least those I found so far):
ScrollPattern.VerticalScrollPercentProperty
ScrollPattern.VerticalViewSizeProperty
I can also go and look for the scrollbar it self and read the following values:
RangeValuePattern.LargeChangeProperty
RangeValuePattern.MaximumProperty
RangeValuePattern.MinimumProperty
RangeValuePattern.SmallChangeProperty
RangeValuePattern.ValueProperty
To look for the scrollbar, I use the following code:
var hWnd = (IntPtr)WordUtils.GetHwnd();
var processId = Process.GetCurrentProcess().Id;
var uiApp = Ts.Application.Attach((int)processId);
var uiWindow = uiApp.GetWindow(WindowHandling.GetWindowText(hWnd), InitializeOption.NoCache);
var wf = (IUIItemContainer)uiWindow.Get(SearchCriteria.ByClassName("_WwF"));
var wbs = wf.GetMultiple(SearchCriteria.ByClassName("_WwB"));
if (wbs.Length != 1)
return;
var wb = (IUIItemContainer)wbs.First();
var wgs= wb.GetMultiple(SearchCriteria.ByClassName("_WwG"));
if (wgs.Length != 1)
return;
var nUiScrollBars = wgs.GetMultiple(SearchCriteria.ByClassName("NUIScrollbar"));
if (scrollBar.Length != 1)
return;
var nUiScrollBar = (IUIItemContainer)nUiScrollBars.First();
var nUiHwndElements = nUiScrollBar.GetMultiple(SearchCriteria.ByClassName("NetUIHWNDElement"));
if (nUiHwndElements.Length != 1)
return;
var nUiHwndElement = (IUIItemContainer)nUiHwndElements.First();
var netUiScrollBar = nUiHwndElement.GetElement(SearchCriteria.ByClassName("NetUIScrollBar"));
var scrollBarValue = (double)netUiScrollBar.GetCurrentPropertyValue(RangeValuePattern.ValueProperty);
You may ask yourself, why I dont set the RangeValuePattern.ValueProperty
when I am able to access it, the problem there is that Word doesnt update the document when I change this property, the scroll thumb does move but the document doesnt move an inch.
I have to set the ScrollPattern.VerticalScrollPercentProperty
for it to work.
So my question, is how do I calculate the new ScrollPattern.VerticalScrollPercentProperty
based on the oldValue, where the document could shrink or grow in size in between?
Edit:
Here is a testscenario:
scrollPercent 64.86486486486487
scrollViewSize 74.394463667820062
scrollBarLargeChange 37197
scrollBarMaximum 12803
scrollBarMinimum 0
scrollBarSmallChange 1
scrollBarValue 8304
After inserting 5 new pages
scrollPercent 87.890366182251867 <-- undesired scrolling occured (see desired values below)
scrollViewSize 9.442248572683356
scrollBarLargeChange 4721
scrollBarMaximum 45279
scrollBarMinimum 0
scrollBarSmallChange 1
scrollBarValue 39795 <-- undesired scrolling occured (see desired values below)
And as said, I need to adjust the scrollPercent - after inserting those pages - so that it is again on the old position.
I can tell you that in this testscenario, I would need the new value to be
scrollPercent 2.3278413357480452
after changing it to the desired percentValue the scrollBarValue is the only value getting updated and it is than at
scrollBarValue 1054
So, it looks like your scrollPercent
is calculated like this:
scrollPercent = 100.0 * scrollBarValue / (scrollBarMaximum - 1);
So the math should work out like this (assuming floating-point division):
scrollPercentOld = 100.0 * scrollBarValueOld / (scrollBarMaximumOld - 1)
scrollPercentNew = 100.0 * scrollBarValueOld / (scrollBarMaximumNew - 1)
From that, you have:
scrollBarValueOld = scrollPercentOld * (scrollBarMaximumOld - 1) / 100.0
scrollBarValueOld = scrollPercentNew * (scrollBarMaximumNew - 1) / 100.0
When you equate the two, you get:
scrollPercentOld * (scrollBarMaximumOld - 1) = scrollPercentNew * (scrollBarMaximumNew - 1)
And then finally:
scrollPercentNew = scrollPercentOld * (scrollBarMaximumOld - 1) / (scrollBarMaximumNew - 1)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With