I am re-posting
my question from Stack Overflow here for more exposure.
I need to move several external application windows at the same time (together) as a group to simulate scrolling functionality.
If your first thought is "why would you want to do that" or "you should never do that", just pretend that it's a good idea and would be fantastic.
So far I have tried the PInvoke methods MoveWindow, SetWindowPos, and (BeginDeferWindowPos, DeferWindowPos, EndDeferWindowPos).
All of these methods produce about the same performance. Moving one window is super snappy, two windows is no big deal, but once I try to move three or more windows things start to get ugly. Here is a snippet using the deferred method to show you how I am doing things and keeping track of performance.
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, tmp.WidgetWidth, tmp.WidgetHeight, SWP.NOREDRAW);
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." );
}
The result for moving 4 windows, 320px left, 1px at a time?
> 1280 move requests made in 14.445 sec.
As you can imagine, waiting 14.5 seconds to see 4 windows make their way across the screen 320 pixels is painful to watch.
- How can this be accomplished in a fluid manner?
Yes, I realize that I can move more than 1px at a time, but that won't resolve the underlying issue. The way I understand it, using any of the PInvoke methods to move windows posts messages to the WinAPI message pump (WndProc()) and waits for the message to be closed / caught / handled before posting the next message. I think this is where I am spending that 14.5 seconds - waiting for messages to be handled.
I have tried using SWP ASYNCWINDOWPOS and the result is horrendous. Each window only gets a few dozen of the messages seemingly at random so that windows are overlapping and as a whole the train barely moves.
The closest I've come to a solution is to assign each "widget" a parent (for example a WindowsFormsHost + an MDI window) and putting them in a form/window and then scrolling that form/window. However I have several reasons for not wanting to do that.
Please help!