计算新的滚动百分比 - 在视图大小改变后

10

首先,基本上我相信我只需要帮助计算它,数学并不是我的强项。

顺便说一下,MS-Word很可能与解决我的问题无关,我基本上只是提到它以便您了解我的情况,但我相信即使没有MS-Word的知识,也应该能够解决我的问题。

我的问题是Word具有属性VerticalPercentScrolled,它是一个整数

这不太准确,而我需要更加准确的值。考虑一个有300页的Word文档,滚动条只能设置0-100(百分比)之间的整数,因此例如在300页文档中,25%是一个相当大的范围。

现在,我已经使用UI Automation库(TestStack.White)读取了正确的值,并且可以成功地将其设置为旧值,如果发生了一些不必要的滚动。

像这样:

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);

使用这段代码,我得到了百分比值,比如说9.442248572683356而不是9

要重置该值,请使用以下代码:

object scrollPattern;
if (element.TryGetCurrentPattern(ScrollPattern.Pattern, out scrollPattern))
    ((ScrollPattern)scrollPattern).SetScrollPercent(ScrollPattern.NoScroll, oldVerticalPercent);

这个功能非常好用。

现在我的问题是,如果我存储了旧值并想重新应用它时,我的文档在此期间变得更大/更小,那么我的旧值需要进行调整。

我可以读取以下值(至少是我目前发现的):

  1. ScrollPattern.VerticalScrollPercentProperty
  2. ScrollPattern.VerticalViewSizeProperty

我也可以去查找滚动条本身并读取以下值:

  1. RangeValuePattern.LargeChangeProperty
  2. RangeValuePattern.MaximumProperty
  3. RangeValuePattern.MinimumProperty
  4. RangeValuePattern.SmallChangeProperty
  5. RangeValuePattern.ValueProperty

要查找滚动条,我使用以下代码:

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);

如果我能够访问RangeValuePattern.ValueProperty,为什么不设置它呢?问题在于,当我更改此属性时,Word不会更新文档,滚动条会移动,但文档没有移动一英寸。

我必须设置ScrollPattern.VerticalScrollPercentProperty才能使其起作用。

那么我的问题是,如何根据可能在其中缩小或扩大的文档大小计算新的ScrollPattern.VerticalScrollPercentProperty值?

编辑:

这里是一个测试场景:

scrollPercent       64.86486486486487
scrollViewSize      74.394463667820062
scrollBarLargeChange    37197
scrollBarMaximum        12803
scrollBarMinimum        0
scrollBarSmallChange    1
scrollBarValue      8304

插入了5个新页面后

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)

正如所说,我需要调整滚动百分比 - 在插入这些页面后 - 以便它再次处于旧位置。

我可以告诉你,在这个测试场景中,我需要新值为

scrollPercent       2.3278413357480452

将其更改为所需的百分比值后,scrollBarValue是唯一更新的值,然后处于该值。

scrollBarValue      1054

你确定scrollPercent的新值应该是2.32吗?我认为它应该是18.339627642。如果是2.32,那你是怎么得到这个值的? - Rob Anthony
@RobAnthony 我滚动到了与第一次相同的位置,但是我得到了这个结果,我还尝试将其硬编码到计算应该发生的位置,它可以正常工作。 - Rand Random
我无法理解你在示例中给出的数字。ScrollPercent、ScrollBarMaximum和ScrollBarValue之间的关系很容易理解,即ScrollPercent = ScrollBarValue / ScrollBarMaximum。这适用于两组数字。它还将2.32值与1054和45279连接起来,但如果您完成了大小为12803的文档的64%,则完成了大小为45279的文档的18%,而不是2.32%。 - Rob Anthony
@RobAnthony 我认为你没有考虑到当ViewSize相对较小且滚动条拇指相当大时,滚动值不是拇指的顶部,我认为它是底部。因此,您会得到不同的结果。我认为当您比较滚动条最大值和大变化时,可以看到这一点,大变化比滚动最大值要大得多。 - Rand Random
1个回答

1
所以,看起来你的 scrollPercent 是这样计算的:
scrollPercent = 100.0 * scrollBarValue / (scrollBarMaximum - 1);

所以数学计算应该是这样的(假设使用浮点数除法):
scrollPercentOld = 100.0 * scrollBarValueOld / (scrollBarMaximumOld - 1)
scrollPercentNew = 100.0 * scrollBarValueOld / (scrollBarMaximumNew - 1)

从那里,你有:
scrollBarValueOld = scrollPercentOld * (scrollBarMaximumOld - 1) / 100.0
scrollBarValueOld = scrollPercentNew * (scrollBarMaximumNew - 1) / 100.0

当你将它们等同起来,你会得到:

scrollPercentOld * (scrollBarMaximumOld - 1) = scrollPercentNew * (scrollBarMaximumNew - 1)

然后最后:

scrollPercentNew = scrollPercentOld * (scrollBarMaximumOld - 1) / (scrollBarMaximumNew - 1)

“总高度”是多少?我可以假设它是“scrollbarMaximum”吗? - Rand Random
我刚刚编辑了我的答案,使用了你问题中的术语和名称。 我刚刚做了一些计算,看起来“总高度”对应于(scrollBarMaximum - 1) - Filip Milovanović
这就是我手动将位置移动到之前的地方时得到的新值,这就是原因。 - Rand Random
你是否在当前滚动位置之前的位置插入或删除页面?如果是这样,那么我提出的方法将无法奏效,你需要想办法跟踪这些更改。 - Filip Milovanović
嗯...你确定你没有混淆来自两个不同测试的值吗? - Filip Milovanović
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接