簡體   English   中英

設置為Windows窗體應用程序中的第三方對話框

[英]Set to foreground a third party dialog in a Windows Form Application

早上好。

我發瘋了,期待着解決一個非常極端的問題。 希望有人能分享一些經驗。

我正在開發OCR排序軟件; 為了與文檔掃描儀通信,我使用了不錯的NTwain庫。
當掃描儀驅動程序有話要說時(發生錯誤,卡紙,進紙器已空等),它會自動彈出對話框,因此您無法控制它們。
問題是那些消息仍保留在后台,被我的應用程序主窗體隱藏,而我不知道如何將它們放在前台。

使用user32.dll互操作方法是一種選擇,但是我可以弄清楚引發掃描儀驅動程序對話框的過程; 為用戶提供了不同制造商使用不同模型的可能性,我不能依靠對話框標題或類似名稱,因為它們因模型而異。

有人有主意嗎?
在Windows中,有一個C:\\Windows\\TWAIN.dll和一個C:\\Windows\\twain_32.dll ,使操作系統可以與掃描儀驅動程序進行通信:使用user32.dll,可以找到從特定窗口打開的窗口。 dll,就像可以處理進程一樣?

我在交叉手指:)
再見南多

我終於找到了解決我的問題的棘手/部分解決方案。
與之前所說的(至少對於佳能掃描儀而言)不同,似乎驅動程序對話框消息框是我主進程窗口的子級 終於有了一些User32.dll互操作性 黑魔法和計時器,我終於將那該死的小窗口移到了前台,讓用戶閱讀並選擇要做什么。

這里的代碼。

#region Usings
using System;
using System.Collections;


#endregion


namespace EProm.Common.PInvoke
{
    /// <summary>
    /// Catch process child windows, setting them in foreground.
    /// <see cref="http://stackoverflow.com/questions/28559726/set-to-foreground-a-third-party-dialog-in-a-windows-form-application"/>
    /// </summary>
    public class DialogsCatcher
    {
        #region Fields
        private readonly ILog _log;
        private readonly int _processId;
        private readonly Timer _timer;
        private readonly IntPtr _windowHandle;
        #endregion


        #region Constructors
        public DialogsCatcher(int processId, int interval, IntPtr windowHandle)
        {
            _log = LogManager.GetLogger(GetType().Name);

            _processId = processId;
            _windowHandle = windowHandle;

            _timer = new Timer();
            _timer.Elapsed += new ElapsedEventHandler(CatchDialogs);
            _timer.Enabled = true;
            _timer.Interval = interval;

            _log.Debug("DialogsCatcher initialized.");
        }
        #endregion


        #region Public Methods
        public void StartMonitoring()
        {
            _timer.Start();

            _log.Debug("DialogsCatcher started.");
        }

        public void StopMonitoring()
        {
            _timer.Stop();

            _log.Debug("DialogsCatcher stopped.");
        }
        #endregion


        #region Private Methods
        private void CatchDialogs(object sender, EventArgs e)
        {
            GetProcessOpenedWindowsByProcessId(_processId, _windowHandle);
        }

        //nando20150219: meaningful names, you're doin' it right! :)
        private void GetProcessOpenedWindowsByProcessId(int processId, IntPtr windowHandle)
        {
            var shellWindowHandle = User32.GetShellWindow();
            var windows = new Dictionary<IntPtr, string>();

            EnumWindowsProc filter = (windowHandle, lp) =>
            {
                int length = User32.GetWindowTextLength(windowHandle);

                var windowText = new StringBuilder(length);
                User32.GetWindowText(windowHandle, windowText, length + 1);
                windows.Add(windowHandle, windowText.ToString());

                var isWindowVisible = User32.IsWindowVisible(windowHandle);

                if (windowHandle == shellWindowHandle)
                {
                return true;
                }

                if (!isWindowVisible)
                {
                    return true;
                }

                if (length == 0)
                {
                    return true;
                }

                uint windowPid;
                User32.GetWindowThreadProcessId(windowHandle, out windowPid);
                if (windowPid != processId)
                {
                    return true;
                }

                if (windowHandle != windowHandle)
                {
                    //nando20150218: set window to foreground
                    User32.SetForegroundWindow(windowHandle);
                    _log.DebugFormat("Window \"{0}\" moved to foreground.", windowText);
                }

                return true;
            };
            User32.EnumWindows(filter, 0);

#if DEBUG
            //foreach (var dictWindow in windows)
            //{
            //  _log.DebugFormat("WindowHandle: {0} - WindowTitle: {1}", dictWindow.Key, dictWindow.Value);
            //}
#endif 
        }
        #endregion
    }


    #region Delegates
    public delegate bool EnumWindowsProc(IntPtr windowHandle, IntPtr lp);

    public delegate bool EnumedWindow(IntPtr windowHandle, ArrayList windsowHandles);
    #endregion


    /// <summary>
    /// Windows User32.dll wrapper
    /// </summary>
    /// <see cref="http://pinvoke.net/"/>
    public class User32
    {
        #region Public Methods
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool IsWindowVisible(IntPtr hWnd);

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

        [DllImport("user32.dll", SetLastError = true)]
        public static extern uint GetWindowThreadProcessId(IntPtr hwnd, out uint lpdwProcessId);

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

        [DllImport("user32.DLL")]
        public static extern bool EnumWindows(EnumWindowsProc enumFunc, int lParam);

        [DllImport("user32.DLL")]
        public static extern int GetWindowTextLength(IntPtr hWnd);

        [DllImport("user32.DLL")]
        public static extern IntPtr GetShellWindow();
        #endregion
    }
}

再見風滾草.... :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM