Skip to content
This repository was archived by the owner on Dec 18, 2023. It is now read-only.

Commit d039712

Browse files
committed
clean up interop methods and values
1 parent 39b54c5 commit d039712

File tree

9 files changed

+373
-274
lines changed

9 files changed

+373
-274
lines changed

CookPopularCSharpToolkit/Windows/Extensions/WindowExtension.cs

Lines changed: 55 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -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;

CookPopularCSharpToolkit/Windows/Interop/InteropMethods.cs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.Text;
1212
using System.Threading;
1313

14+
1415
namespace CookPopularCSharpToolkit.Windows.Interop
1516
{
1617
internal class InteropMethods
@@ -68,11 +69,11 @@ internal static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
6869
internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
6970

7071
[DllImport(InteropValues.ExternDll.User32, SetLastError = true)]
71-
internal static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass,
72-
string lpszWindow);
72+
internal static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
7373

74-
[DllImport(InteropValues.ExternDll.User32)]
75-
internal static extern int GetWindowRect(IntPtr hwnd, out InteropValues.RECT lpRect);
74+
[DllImport(InteropValues.ExternDll.User32, SetLastError = true)]
75+
[return: MarshalAs(UnmanagedType.Bool)]
76+
internal static extern bool GetWindowRect(IntPtr hwnd, out InteropValues.RECT lpRect);
7677

7778
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Auto)]
7879
internal static extern bool GetCursorPos(out InteropValues.POINT pt);
@@ -361,9 +362,9 @@ internal static InteropValues.WINDOWPLACEMENT GetWindowPlacement(IntPtr hwnd)
361362
[return: MarshalAs(UnmanagedType.Bool)]
362363
internal static extern bool IsZoomed(IntPtr hwnd);
363364

364-
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Auto, ExactSpelling = true)]
365+
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
365366
[return: MarshalAs(UnmanagedType.Bool)]
366-
internal static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, int flags);
367+
internal static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, InteropValues.WindowPositionFlags flags);
367368

368369
internal static System.Windows.Point GetCursorPos()
369370
{
@@ -376,8 +377,8 @@ internal static System.Windows.Point GetCursorPos()
376377
return result;
377378
}
378379

379-
[DllImport(InteropValues.ExternDll.User32)]
380-
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
380+
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Auto, SetLastError = true)]
381+
internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);
381382

382383
internal static int GetWindowLong(IntPtr hWnd, InteropValues.GWL nIndex) => GetWindowLong(hWnd, (int)nIndex);
383384

@@ -515,6 +516,21 @@ internal static IntPtr SetWindowLongPtr(IntPtr hWnd, InteropValues.GWLP nIndex,
515516
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Auto)]
516517
internal static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
517518

519+
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Auto, SetLastError = true)]
520+
internal static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
521+
522+
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Auto, SetLastError = true)]
523+
internal static extern bool FlashWindowEx(ref InteropValues.FLASHWINFO pwfi);
524+
525+
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Auto, SetLastError = true)]
526+
internal static extern IntPtr GetTopWindow(IntPtr hWnd);
527+
528+
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Auto, SetLastError = true)]
529+
internal static extern IntPtr SetFocus(IntPtr hWnd);
530+
531+
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Auto, SetLastError = true)]
532+
internal static extern IntPtr GetFocus();
533+
518534
#endregion
519535

520536

0 commit comments

Comments
 (0)