Question

I use the WIA ShowTransfer method to scan a picture from a device from within my WPF application. But the user is able to set the focus on the WPF application and then the progress bar displayed by WIA hides behind the WPF application. How can I force the progress bar to stay on top of everything?

Was it helpful?

Solution

I tried several things, e.g. enumerate all running processes, enumerate all windows by the WPF application, but no luck. This is what finally helped:

#region Force Scan Progress to front hack

[DllImport("user32.dll", EntryPoint = "EnumDesktopWindows", ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDelegate lpEnumCallbackFunction, IntPtr lParam);

[DllImport("user32.dll", EntryPoint = "GetWindowText", ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
private static extern int _GetWindowText(IntPtr hWnd, StringBuilder lpWindowText, int nMaxCount);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWindowVisible(IntPtr hWnd);

[DllImport("user32.dll")]
public static extern int SetForegroundWindow(IntPtr hWnd);

const int MAXTITLE = 255;

private delegate bool EnumDelegate(IntPtr hWnd, int lParam);

public static string GetWindowText(IntPtr hWnd)
{
    StringBuilder strbTitle = new StringBuilder(MAXTITLE);
    int nLength = _GetWindowText(hWnd, strbTitle, strbTitle.Capacity + 1);
    strbTitle.Length = nLength;
    return strbTitle.ToString();
}

private static bool EnumWindowsProc(IntPtr hWnd, int lParam)
{
    string strTitle = GetWindowText(hWnd);
    if (strTitle.StartsWith("Title of progress bar")) SetForegroundWindow(hWnd);
    return true;
}

private void forceScanProgressToFront(object source, EventArgs ea)
{
    EnumDelegate delEnumfunc = new EnumDelegate(EnumWindowsProc);
    bool bSuccessful = EnumDesktopWindows(IntPtr.Zero, delEnumfunc, IntPtr.Zero);
    if (!bSuccessful)
    {
        // Get the last Win32 error code
        int nErrorCode = Marshal.GetLastWin32Error();
        string strErrMsg = String.Format("EnumDesktopWindows failed with code {0}.", nErrorCode);
        throw new Exception(strErrMsg);
    }
}

#endregion

I bind this to a DispatcherTimer which fires every 500ms. So even if the user tries to hide the progress bar it pops up every 500ms.

See also: http://hintdesk.com/how-to-enumerate-all-opened-windows/

OTHER TIPS

The solution is to call ShowTransfer method from the UI thread, not from a worker thread.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top