5ce2c8a982
为 Claude Code 提供原生 Windows toast 通知:点击跳回原窗口、切回 Windows Terminal 标签、跨虚拟桌面、调用方图标、非阻塞投递;NativeAOT 单文件分发。
73 lines
2.3 KiB
C#
73 lines
2.3 KiB
C#
using System;
|
|
|
|
namespace Notify.Interop;
|
|
|
|
/// <summary>
|
|
/// 把目标窗口拉回前台
|
|
///
|
|
/// Windows 限制后台进程抢焦点,这里用一套组合技绕过:ALT 键模拟 +
|
|
/// AttachThreadInput 把当前线程与前台/目标线程的输入队列挂接 +
|
|
/// SetWindowPos/BringWindowToTop/SwitchToThisWindow/SetForegroundWindow 多管齐下
|
|
/// </summary>
|
|
public static class WindowActivator
|
|
{
|
|
public static bool Activate(IntPtr hwnd)
|
|
{
|
|
if (hwnd == IntPtr.Zero || !Win32.IsWindow(hwnd))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
// 最小化的先还原
|
|
if (Win32.IsIconic(hwnd))
|
|
{
|
|
Win32.ShowWindow(hwnd, Win32.SW_RESTORE);
|
|
}
|
|
|
|
var foreground = Win32.GetForegroundWindow();
|
|
var curThread = Win32.GetCurrentThreadId();
|
|
var fgThread = Win32.GetWindowThreadProcessId(foreground, out _);
|
|
var targetThread = Win32.GetWindowThreadProcessId(hwnd, out _);
|
|
|
|
// 模拟一次 ALT 抬起,满足 Windows 的"防焦点抢占"前置条件
|
|
Win32.keybd_event(Win32.VK_MENU, 0, 0, IntPtr.Zero);
|
|
Win32.keybd_event(Win32.VK_MENU, 0, Win32.KEYEVENTF_KEYUP, IntPtr.Zero);
|
|
|
|
if (fgThread != curThread)
|
|
{
|
|
Win32.AttachThreadInput(curThread, fgThread, true);
|
|
}
|
|
|
|
if (targetThread != curThread && targetThread != fgThread)
|
|
{
|
|
Win32.AttachThreadInput(curThread, targetThread, true);
|
|
}
|
|
|
|
Win32.AllowSetForegroundWindow(Win32.ASFW_ANY);
|
|
Win32.SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, Win32.SWP_NOMOVE | Win32.SWP_NOSIZE | Win32.SWP_SHOWWINDOW);
|
|
Win32.BringWindowToTop(hwnd);
|
|
Win32.SwitchToThisWindow(hwnd, true);
|
|
Win32.SetForegroundWindow(hwnd);
|
|
Win32.ShowWindow(hwnd, Win32.SW_SHOW);
|
|
|
|
if (targetThread != curThread && targetThread != fgThread)
|
|
{
|
|
Win32.AttachThreadInput(curThread, targetThread, false);
|
|
}
|
|
|
|
if (fgThread != curThread)
|
|
{
|
|
Win32.AttachThreadInput(curThread, fgThread, false);
|
|
}
|
|
|
|
return Win32.GetForegroundWindow() == hwnd;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|