我需要同时(一起)移动几个外部应用程序窗口作为一组来模拟滚动功能。
如果你的第一个想法是“你为什么要这样做”或“你永远不应该那样做”,那就假装这是一个好主意并且会很棒。
到目前为止,我已尝试过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秒仍无法使用。
是的,我意识到我一次可以移动超过1个像素,但这无法解决根本问题。我理解它的方式,使用任何PInvoke方法移动窗口将消息发布到WinAPI消息泵(WndProc())并在发布下一条消息之前等待消息被关闭/捕获/处理。我认为这是我花费14.5秒的时间 - 等待消息处理。
我尝试过使用SWP ASYNCWINDOWPOS,结果很可怕。每个窗口只能看到几十个看似随机的消息,因此窗口重叠,整个火车几乎不动。
我最接近解决方案是为每个“窗口小部件”分配一个父窗口(例如WindowsFormsHost +一个MDI窗口)并将它们放在窗体/窗口中,然后滚动该窗体/窗口。但是我有几个理由不想这样做。
更新:有关CodeProject的更多信息,我已复制此问题。
<小时/>
添加SWP标志有很多帮助,但我确定实际上减慢了很多东西是我的测试应用程序。每次移动4个这样的WPF窗口,我把它缩短到大约8.5秒。
当我更换一个标准空记事本的测试窗口时,它下降到0.6秒,这对我来说是可以的。因此,我非常有信心代码是合理的。因此,当使用与时间相关的移动偏移(受控运动)程序实现此代码时,问题变为如何最小化窗口闪烁。 这仍然是一项正在进行的工作,所以我很感激任何建议。