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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//==============================================================================
//  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
    {
        [ThreadStatic]
        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 && ComponentDispatcher.IsThreadModal)
            {
                bool actived = false;
                foreach (Window w in Application.Current.Windows)
                {
                    HwndSource src = HwndSource.FromVisual(w) as HwndSource;
                    if (src != null /*&& 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));
                }
            }
        }
 
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        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;
        }
    }
}
posted @   葡萄城技术团队  阅读(1191)  评论(1编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示