@@ -22,127 +22,12 @@ namespace CookPopularCSharpToolkit.Windows
2222 [ SuppressMessage ( "Security" , "CA2153:不要捕获损坏状态异常" , Justification = "<挂起>" ) ]
2323 public static class WindowExtension
2424 {
25- internal static class NativeMethods
26- {
27- [ Flags ]
28- [ SuppressMessage ( "Design" , "CA1069:不应复制枚举值" , Justification = "<挂起>" ) ]
29- internal enum SWP : uint
30- {
31- NOSIZE = 0x0001 ,
32- NOMOVE = 0x0002 ,
33- NOZORDER = 0x0004 ,
34- NOREDRAW = 0x0008 ,
35- NOACTIVATE = 0x0010 ,
36- DRAWFRAME = 0x0020 ,
37- FRAMECHANGED = 0x0020 ,
38- SHOWWINDOW = 0x0040 ,
39- HIDEWINDOW = 0x0080 ,
40- NOCOPYBITS = 0x0100 ,
41- NOOWNERZORDER = 0x0200 ,
42- NOREPOSITION = 0x0200 ,
43- NOSENDCHANGING = 0x0400 ,
44- DEFERERASE = 0x2000 ,
45- ASYNCWINDOWPOS = 0x4000 ,
46- }
47-
48- internal enum FlashType : uint
49- {
50- /// <summary>
51- /// 停止闪烁。
52- /// </summary>
53- FLASHW_STOP = 0 ,
54-
55- /// <summary>
56- /// 只闪烁标题。
57- /// </summary>
58- FALSHW_CAPTION = 1 ,
59-
60- /// <summary>
61- /// 只闪烁任务栏。
62- /// </summary>
63- FLASHW_TRAY = 2 ,
64-
65- /// <summary>
66- /// 标题和任务栏同时闪烁。
67- /// </summary>
68- FLASHW_ALL = 3 ,
69-
70- /// <summary>
71- ///
72- /// </summary>
73- FLASHW_PARAM1 = 4 ,
74-
75- /// <summary>
76- ///
77- /// </summary>
78- FLASHW_PARAM2 = 12 ,
79-
80- /// <summary>
81- /// 无条件闪烁任务栏直到发送停止标志或者窗口被激活,如果未激活,停止时高亮。
82- /// </summary>
83- FLASHW_TIMER = FLASHW_TRAY | FLASHW_PARAM1 ,
84-
85- /// <summary>
86- /// 未激活时闪烁任务栏直到发送停止标志或者窗体被激活,停止后高亮。
87- /// </summary>
88- FLASHW_TIMERNOFG = FLASHW_TRAY | FLASHW_PARAM2 ,
89- }
90-
91- /// <summary>
92- /// 包含系统应在指定时间内闪烁窗口次数和闪烁状态的信息
93- /// </summary>
94- internal struct FLASHWINFO
95- {
96- /// <summary>
97- /// 结构大小
98- /// </summary>
99- public uint cbSize ;
100-
101- /// <summary>
102- /// 要闪烁或停止的窗口句柄
103- /// </summary>
104- public IntPtr hwnd ;
105-
106- /// <summary>
107- /// 闪烁的类型
108- /// </summary>
109- public uint dwFlags ;
110-
111- /// <summary>
112- /// 闪烁窗口的次数
113- /// </summary>
114- public uint uCount ;
115-
116- /// <summary>
117- /// 窗口闪烁的频度,毫秒为单位;若该值为0,则为默认图标的闪烁频度
118- /// </summary>
119- public uint dwTimeout ;
120- }
121-
122- internal const int HWND_NOTOPMOST = - 2 ;
123- internal const int HWND_TOPMOST = - 1 ;
124- internal const int HWND_TOP = 0 ;
125- internal const int HWND_BOTTOM = 1 ;
126-
127- internal const int GWL_EXSTYLE = - 20 ;
128- internal const int WS_EX_DLGMODALFRAME = 0x0001 ;
129- internal const uint WS_EX_TOPMOST = 0x0008 ;
130-
131- [ DllImport ( "user32.dll" ) ]
132- internal static extern bool SetWindowPos ( IntPtr hWnd , int hWndInsertAfter , int X , int Y , int cx , int cy , SWP uFlags ) ;
133-
134- [ DllImport ( "user32.dll" , SetLastError = true ) ]
135- internal static extern int GetWindowLong ( IntPtr hWnd , int nIndex ) ;
136-
137- //[DllImport("user32.dll")]
138- //internal static extern bool SetForegroundWindow(IntPtr hWnd);
139-
140- [ DllImport ( "user32.dll" , SetLastError = true ) ]
141- internal static extern void SwitchToThisWindow ( IntPtr hWnd , bool fAltTab ) ;
142-
143- [ DllImport ( "user32.dll" ) ]
144- internal static extern bool FlashWindowEx ( ref FLASHWINFO pwfi ) ;
145- }
25+ internal const int HWND_NOTOPMOST = - 2 ;
26+ internal const int HWND_TOPMOST = - 1 ;
27+ internal const int HWND_TOP = 0 ;
28+ internal const int HWND_BOTTOM = 1 ;
29+ internal const int WS_EX_DLGMODALFRAME = 0x0001 ;
30+ internal const uint WS_EX_TOPMOST = 0x0008 ;
14631
14732 private static readonly Func < Window , bool > getDisposedValue = CreateGetFieldValueDelegate < Window , bool > ( "_disposed" ) ;
14833 private static readonly Func < Window , bool > getIsClosingValue = CreateGetFieldValueDelegate < Window , bool > ( "_isClosing" ) ;
@@ -153,7 +38,7 @@ internal struct FLASHWINFO
15338
15439 public static HwndSource GetHwndSource ( this Window window ) => HwndSource . FromHwnd ( window . EnsureHandle ( ) ) ;
15540
156- public static void SwitchToThisWindow ( this Window window ) => NativeMethods . SwitchToThisWindow ( window . EnsureHandle ( ) , true ) ;
41+ public static void SwitchToThisWindow ( this Window window ) => InteropMethods . SwitchToThisWindow ( window . EnsureHandle ( ) , true ) ;
15742
15843 public static Window SetOwner ( this Window window , IntPtr hWnd )
15944 {
@@ -170,12 +55,11 @@ public static void RemoveIcon(this Window window)
17055 IntPtr hwnd = new WindowInteropHelper ( window ) . Handle ;
17156
17257 //改变窗体的样式
173- int extendedStyle = NativeMethods . GetWindowLong ( hwnd , NativeMethods . GWL_EXSTYLE ) ;
174- Interop . NativeMethods . SetWindowLong ( hwnd , NativeMethods . GWL_EXSTYLE , extendedStyle | NativeMethods . WS_EX_DLGMODALFRAME ) ;
58+ int extendedStyle = InteropMethods . GetWindowLong ( hwnd , ( int ) InteropValues . GetWindowLongFields . GWL_EXSTYLE ) ;
59+ InteropMethods . SetWindowLong ( hwnd , ( int ) InteropValues . GetWindowLongFields . GWL_EXSTYLE , new IntPtr ( extendedStyle | WS_EX_DLGMODALFRAME ) ) ;
17560
17661 //更新窗口的非客户区,以反映变化
177- Interop . NativeMethods . SetWindowPos ( hwnd , IntPtr . Zero , 0 , 0 , 0 , 0 , Interop . NativeMethods . SWP . NOMOVE |
178- Interop . NativeMethods . SWP . NOSIZE | Interop . NativeMethods . SWP . NOZORDER | Interop . NativeMethods . SWP . FRAMECHANGED ) ;
62+ InteropMethods . SetWindowPos ( hwnd , IntPtr . Zero , 0 , 0 , 0 , 0 , InteropValues . WindowPositionFlags . SWP_NOMOVE | InteropValues . WindowPositionFlags . SWP_NOSIZE | InteropValues . WindowPositionFlags . SWP_NOZORDER | InteropValues . WindowPositionFlags . SWP_FRAMECHANGED ) ;
17963 }
18064
18165 /// <summary>
@@ -245,6 +129,43 @@ public static bool SafeActivate(this Window window)
245129 }
246130 }
247131
132+ /// <summary>
133+ /// 让窗口激活作为前台最上层窗口
134+ /// </summary>
135+ /// <param name="window"></param>
136+ public static void SetWindowToForeground ( Window window )
137+ {
138+ // [WPF 让窗口激活作为前台最上层窗口的方法 - lindexi - 博客园](https://www.cnblogs.com/lindexi/p/12749671.html)
139+ var interopHelper = new WindowInteropHelper ( window ) ;
140+ var thisWindowThreadId = InteropMethods . GetWindowThreadProcessId ( interopHelper . Handle , out _ ) ;
141+ var currentForegroundWindow = InteropMethods . GetForegroundWindow ( ) ;
142+ var currentForegroundWindowThreadId = InteropMethods . GetWindowThreadProcessId ( currentForegroundWindow , out _ ) ;
143+
144+ // [c# - Bring a window to the front in WPF - Stack Overflow](https://stackoverflow.com/questions/257587/bring-a-window-to-the-front-in-wpf )
145+ // [SetForegroundWindow的正确用法 - 子坞 - 博客园](https://www.cnblogs.com/ziwuge/archive/2012/01/06/2315342.html )
146+ /*
147+ 1.得到窗口句柄FindWindow
148+ 2.切换键盘输入焦点AttachThreadInput
149+ 3.显示窗口ShowWindow(有些窗口被最小化/隐藏了)
150+ 4.更改窗口的Z Order,SetWindowPos使之最上,为了不影响后续窗口的Z Order,改完之后,再还原
151+ 5.最后SetForegroundWindow
152+ */
153+
154+ InteropMethods . AttachThreadInput ( currentForegroundWindowThreadId , thisWindowThreadId , true ) ;
155+
156+ window . Show ( ) ;
157+ window . Activate ( ) ;
158+ // 去掉和其他线程的输入链接
159+ InteropMethods . AttachThreadInput ( currentForegroundWindowThreadId , thisWindowThreadId , false ) ;
160+
161+ // 用于踢掉其他的在上层的窗口
162+ if ( window . Topmost != true )
163+ {
164+ window . Topmost = true ;
165+ window . Topmost = false ;
166+ }
167+ }
168+
248169 /// <summary>
249170 /// 闪烁窗口的任务栏图标。
250171 /// </summary>
@@ -256,18 +177,18 @@ public static bool FlashWindow(this Window window, bool IsStopFlash = false)
256177 {
257178 try
258179 {
259- var fInfo = new NativeMethods . FLASHWINFO ( ) ;
180+ var fInfo = new InteropValues . FLASHWINFO ( ) ;
260181
261182 fInfo . cbSize = Convert . ToUInt32 ( Marshal . SizeOf ( fInfo ) ) ;
262183 fInfo . hwnd = new WindowInteropHelper ( window ) . EnsureHandle ( ) ;
263184 if ( ! IsStopFlash )
264- fInfo . dwFlags = ( uint ) ( NativeMethods . FlashType . FLASHW_ALL | NativeMethods . FlashType . FLASHW_TIMER ) ;
185+ fInfo . dwFlags = ( uint ) ( InteropValues . FlashType . FLASHW_ALL | InteropValues . FlashType . FLASHW_TIMER ) ;
265186 else
266- fInfo . dwFlags = ( uint ) NativeMethods . FlashType . FLASHW_STOP ;
187+ fInfo . dwFlags = ( uint ) InteropValues . FlashType . FLASHW_STOP ;
267188 fInfo . uCount = 3 ;
268189 fInfo . dwTimeout = 0 ;
269190
270- return NativeMethods . FlashWindowEx ( ref fInfo ) ;
191+ return InteropMethods . FlashWindowEx ( ref fInfo ) ;
271192 }
272193 catch ( Exception )
273194 {
@@ -345,13 +266,12 @@ private static bool SetTopmostCore(IntPtr hWnd, bool topmost)
345266 if ( Debugger . IsAttached )
346267 return true ;
347268#endif
348- const NativeMethods . SWP uFlags = NativeMethods . SWP . ASYNCWINDOWPOS | NativeMethods . SWP . NOSIZE | NativeMethods . SWP . NOMOVE | NativeMethods . SWP . NOREDRAW | NativeMethods . SWP . NOACTIVATE ;
349-
350- if ( NativeMethods . SetWindowPos ( hWnd , topmost ? NativeMethods . HWND_TOPMOST : NativeMethods . HWND_NOTOPMOST , 0 , 0 , 0 , 0 , uFlags ) )
269+ const InteropValues . WindowPositionFlags uFlags = InteropValues . WindowPositionFlags . SWP_ASYNCWINDOWPOS | InteropValues . WindowPositionFlags . SWP_NOSIZE | InteropValues . WindowPositionFlags . SWP_NOMOVE | InteropValues . WindowPositionFlags . SWP_NOREDRAW | InteropValues . WindowPositionFlags . SWP_NOACTIVATE ;
270+ if ( InteropMethods . SetWindowPos ( hWnd , topmost ? new IntPtr ( HWND_TOPMOST ) : new IntPtr ( HWND_NOTOPMOST ) , 0 , 0 , 0 , 0 , uFlags ) )
351271 {
352- var exStyleWithTopmost = NativeMethods . GetWindowLong ( hWnd , NativeMethods . GWL_EXSTYLE ) & NativeMethods . WS_EX_TOPMOST ;
272+ var exStyleWithTopmost = InteropMethods . GetWindowLong ( hWnd , ( int ) InteropValues . GetWindowLongFields . GWL_EXSTYLE ) & WS_EX_TOPMOST ;
353273
354- return topmost ? ( exStyleWithTopmost == NativeMethods . WS_EX_TOPMOST ) : ( exStyleWithTopmost != NativeMethods . WS_EX_TOPMOST ) ;
274+ return topmost ? ( exStyleWithTopmost == WS_EX_TOPMOST ) : ( exStyleWithTopmost != WS_EX_TOPMOST ) ;
355275 }
356276
357277 return false ;
0 commit comments