У меня было бы максимальное ожидание в несколько секунд, но в течение этого времени я периодически использовал бы функцию Win32 FindWindowEx, чтобы увидеть, действительно ли открывается диалоговое окно печати, и если это так, продолжайте.Вы можете получить главное окно процесса с кодом, подобным следующему:
Process[] processes = Process.GetProcessesByName(appName);
foreach (Process p in processes)
{
IntPtr pFoundWindow = p.MainWindowHandle;
}
Затем вы можете передать дескриптор найденного главного окна в FindWindowEx, чтобы просмотреть дочерние окна для проверки на наличие диалога печати.FindWindowEx имеет подписи PInvoke, такие как:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
Edit 2: Так как OP кажется требовательным, я даю отлично работающую функцию, я написал общую, которая выполняет трюк, и протестировалЭто.Вот он, рабочий общий код для ожидания любого дочернего окна.Вызовите как WaitForChildWindow ("myApp", "Print", 5000) для этого случая:
/// <summary>
/// Wait for a child window of an application to appear
/// </summary>
/// <param name="appName">Application name to check (will check all instances)</param>
/// <param name="childWindowName">Name of child window to look for (titlebar)</param>
/// <param name="timeout">Maximum time, in milliseconds, to wait</param>
/// <returns>True if the window was found; false if it wasn't.</returns>
public static bool WaitForChildWindow(string appName, string childWindowName, int timeout)
{
int sleepTime = timeout;
while (sleepTime > 0)
{
Process[] processes = Process.GetProcessesByName(appName);
foreach (Process p in processes)
{
IntPtr pMainWindow = p.MainWindowHandle;
IntPtr pFoundWindow = FindWindowEx(pMainWindow, IntPtr.Zero, null, childWindowName);
if (pFoundWindow != IntPtr.Zero)
return true;
}
Thread.Sleep(100);
sleepTime -= 100;
}
// Timed out!
return false;
}
Редактировать 3: Вот еще один способ сделать это для окон, находящихся в простой собственности, которые неесть дочерние отношения:
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hwnd, IntPtr processId);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumThreadWindows(uint dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
[DllImport("user32", SetLastError = true, CharSet = CharSet.Auto)]
private extern static int GetWindowText(IntPtr hWnd, StringBuilder text, int maxCount);
public delegate bool EnumThreadDelegate(IntPtr hwnd, IntPtr lParam);
static bool EnumThreadCallback(IntPtr hWnd, IntPtr lParam)
{
StringBuilder text = new StringBuilder(500);
GetWindowText(hWnd, text, 500);
if (text.ToString() == "Print")
return false;
return true;
}
public static bool FindThreadPrintWindow(uint threadId)
{
return !EnumThreadWindows(threadId, EnumThreadCallback, IntPtr.Zero);
}
public static bool WaitForOwnedPrintWindow(string appName, int timeout)
{
int sleepTime = timeout;
while (sleepTime > 0)
{
Process[] processes = Process.GetProcessesByName(appName);
foreach (Process p in processes)
{
IntPtr pMainWindow = p.MainWindowHandle;
uint threadId = GetWindowThreadProcessId(pMainWindow, IntPtr.Zero);
if (FindThreadPrintWindow(threadId))
return true;
}
Thread.Sleep(100);
sleepTime -= 100;
}
// Timed out!
return false;
}