thrall 发表于 2013-5-7 11:27:00

把WPF Dialog转成WinForm Dialog需要注意的问题续

上一篇讲到将WPF的窗口转为WinForm窗口需要注意的问题,这里给出了另一种解决方案,闲话不说,请看代码:


//==============================================================================
//File Name   :   WpfModalDialogFixer.cs
//
//Copyright (C) 2010 GrapeCity Inc. All rights reserved.
//
//Distributable under LGPL license.
//
//==============================================================================

// <fileinformation>
//   <summary>
//   This file defines the class WpfModalDialogFixer for solve the problem as below:
//   When showing a modal dialog which ShowTaskBar is false, first deactive the application the activate it again.
//   The modal dialog would be at behind of MainWindow.
//   </summary>
//   <author name="WinkingZhang" mail="Winking.Zhang@GrapeCity.com"/>
//   <seealso ref=""/>
//   <remarks>
//   
//   </remarks>
// </fileinformation>

// <history>
//   <record date="10/21/2010 6:07:04 PM" author="WinkingZhang" revision="1.00.000">
//   Create the file and define the class.
//   </record>
// </history>

using System;
using System.Threading;
using System.Windows;
using System.Windows.Interop;
using System.Runtime.InteropServices;

namespace GrapeCity.Windows
{
    /// <summary>
    ///   Represents the <see cref="WpfModalDialogFixer"/> class.
    /// </summary>
    public class WpfModalDialogFixer
    {
      
      private static WpfModalDialogFixer _fixer;
      private static readonly object _rootSync = new object();

      static WpfModalDialogFixer()
      {
            ComponentDispatcher.EnterThreadModal += new EventHandler(OnComponentDispatcherEnterThreadModal);
            ComponentDispatcher.LeaveThreadModal += new EventHandler(OnComponentDispatcherLeaveThreadModal);
      }

      private WpfModalDialogFixer()
      {
      }

      static void OnComponentDispatcherLeaveThreadModal(object sender, EventArgs e)
      {
            if (WpfModalDialogFixer.Current.Enable)
            {
                HwndSource src = HwndSource.FromVisual(Application.Current.MainWindow) as HwndSource;
                if (src != null)
                {
                  src.RemoveHook(new HwndSourceHook(OnComponentDispatcherThreadPreprocessMessage));
                }
            }
      }

      static IntPtr OnComponentDispatcherThreadPreprocessMessage(IntPtr hwnd, int message, IntPtr wparam, IntPtr lparam, ref bool handled)
      {
            // Need take care the message: WM_SETFOCUS, and if now in Modal dialog mode.
            if (message == 0x7 &amp;&amp; ComponentDispatcher.IsThreadModal)
            {
                bool actived = false;
                foreach (Window w in Application.Current.Windows)
                {
                  HwndSource src = HwndSource.FromVisual(w) as HwndSource;
                  if (src != null /*&amp;&amp; src.Handle != hwnd*/)
                  {
                        if (IsWindowEnabled(src.Handle))
                        {
                            w.Activate();
                            actived = true;
                            break;
                        }
                  }
                }
                if (!actived) // in this case, caused by MessageBox.Show(...)
                {
                  //TODO: how to handle?
                }
                handled = true; // set handled to prevent default implement.
            }
            return IntPtr.Zero;
      }

      static void OnComponentDispatcherEnterThreadModal(object sender, EventArgs e)
      {
            if (WpfModalDialogFixer.Current.Enable)
            {
                HwndSource src = HwndSource.FromVisual(Application.Current.MainWindow) as HwndSource;
                if (src != null)
                {
                  src.AddHook(new HwndSourceHook(OnComponentDispatcherThreadPreprocessMessage));
                }
            }
      }

      
      
      private static extern bool IsWindowEnabled(IntPtr hwnd);

      public static WpfModalDialogFixer Current
      {
            get
            {
                if (_fixer == null)
                {
                  lock (_rootSync)
                  {
                        if (_fixer == null)
                        {
                            _fixer = new WpfModalDialogFixer();
                        }
                  }
                }
                return _fixer;
            }
      }

      public bool Enable
      {
            get;
            set;
      }
    }
}
页: [1]
查看完整版本: 把WPF Dialog转成WinForm Dialog需要注意的问题续