我需要将多个外部应用程序窗口同时(在一起)作为一组来模拟滚动function。
如果你的第一个想法是“你为什么要这样做”或者“你永远不应该这样做”,那么假装这是一个好主意,而且会很棒。
到目前为止,我已经尝试了PInvoke方法MoveWindow , SetWindowPos和(BeginDeferWindowPos, DeferWindowPos ,EndDeferWindowPos)。
所有这些方法产生大致相同的性能。 移动一个窗口是超级活泼的,两个窗口没有什么大不了的,但是一旦我尝试移动三个或更多的窗口,事情开始变得丑陋。 这是一个使用延迟方法的片段,向您展示我如何做事和跟踪性能。
private void multiMoveWindows(int moveAmt, int startingIndex) { int tempX; int howmanyTimes = 0; int numOfWidgetsToMove = 0; int moveAmtRemaining = moveAmt; IntPtr MultiWindowStructure; System.Diagnostics.Stopwatch t = new Stopwatch(); WidgetTracker[] tmp_WhichWidgets = new WidgetTracker[10]; foreach (KeyValuePair<string, WidgetTracker> entry in m_dictWT) { WidgetTracker tmp = new WidgetTracker(); tmp = entry.Value; if (tmp.WIndex >= startingIndex) { tmp_WhichWidgets[numOfWidgetsToMove] = tmp; ++numOfWidgetsToMove; } } for (int i = 0; i < moveAmtRemaining; i++) { MultiWindowStructure = Native_Methods.BeginDeferWindowPos(numOfWidgetsToMove); foreach (WidgetTracker tmp in tmp_WhichWidgets) { if (tmp != null) { tmp.surveilWidget(); tempX = tmp.WidgetRectLeft - 1; MultiWindowStructure = Native_Methods.DeferWindowPos( MultiWindowStructure, tmp.WidgetHandle, HWND.NOTOPMOST, tempX, tmp.WidgetRectTop, 0, 0, SWP.NOREDRAW | SWP.NOZORDER | SWP.NOACTIVATE | SWP.NOSIZE); howmanyTimes++; } } t.Start(); Native_Methods.EndDeferWindowPos(MultiWindowStructure); t.Stop(); } MessageBox.Show(howmanyTimes.ToString() + " move requests made." + Environment.NewLine + "Execution of EndDeferWindowPos took " + t.Elapsed.Seconds.ToString() + " sec " + t.Elapsed.Milliseconds.ToString() + " ms." ); }
这里是移动4个窗口,每次320px,1px的结果:
正如你可以想象的,等待14.5秒,看到4个窗口在屏幕上穿越320像素是痛苦的观看。
我已经添加了一些SWP标志和改进的性能,但7.5秒仍然不可行。
是的,我意识到我一次可以移动超过1px,但是这并不能解决潜在的问题。 我理解的方式,使用任何PInvoke方法将窗口张贴消息移动到WinAPI消息泵(WndProc()),并等待邮件封闭/捕获/处理,然后张贴下一条消息。 我想这就是我花14.5秒钟等待消息处理的地方。
我曾尝试使用SWP ASYNCWINDOWPOS,结果是可怕的。 每个窗口只能看到随机的几十条消息,使得窗口重叠,整个列车几乎不动。
最接近的解决scheme是将每个“窗口小部件”分配给一个父窗口(例如一个WindowsFormsHost +一个MDI窗口),并将它们放在窗体/窗口中,然后滚动窗体/窗口。 不过,我有几个理由不想这样做。
更新:在CodeProject上我已经重复了这个问题的更多信息。
添加SWP标志帮助了很多,但是我确定实际上放慢速度的东西是我的testing应用程序。 一次移动4个这些WPF窗口,我把它降低到大约8.5秒。
当我把我的testing窗口换成标准的空白记事本时,下降到了0.6秒,这对我的目的来说没问题。 所以我很有信心,代码是健全的。 那么问题就变成了, 如何用时间相关的移动偏移(受控运动)例程来实现这个代码时,最小化窗口闪烁 。
这仍然是一个正在进行的工作,所以我会很感激任何的build议。