Skip to content

Instantly share code, notes, and snippets.

@arturaz
Created January 27, 2022 11:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arturaz/45c27c21146e0b8f035d8646dcab702e to your computer and use it in GitHub Desktop.
Save arturaz/45c27c21146e0b8f035d8646dcab702e to your computer and use it in GitHub Desktop.
// See Utilities.SetWindowTitle.cs for explanation
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && !UNITY_EDITOR)
using System;
using System.Runtime.InteropServices;
using FPCSharpUnity.unity.Logger;
using FPCSharpUnity.unity.Utilities;
using GenerationAttributes;
using FPCSharpUnity.core.exts;
using FPCSharpUnity.core.log;
using static FPCSharpUnity.unity.win32_api.Win32API;
namespace FPCSharpUnity.unity.win32_api {
class FlashWindowWin32 : IFlashWindow {
[LazyProperty] static ILog log => Log.d.withScope(nameof(FlashWindowWin32));
/// Stop flashing. The system restores the window to its original state.
public const uint FLASHW_STOP = 0;
/// Flash the window caption.
public const uint FLASHW_CAPTION = 1;
/// Flash the taskbar button.
public const uint FLASHW_TRAY = 2;
/// Flash both the window caption and taskbar button.
/// This is equivalent to setting the FLASHW_CAPTION | FLASHW_TRAY flags.
public const uint FLASHW_ALL = 3;
/// Flash continuously, until the FLASHW_STOP flag is set.
public const uint FLASHW_TIMER = 4;
/// Flash continuously until the window comes to the foreground.
public const uint FLASHW_TIMERNOFG = 12;
static FLASHWINFO Create_FLASHWINFO(IntPtr handle, uint flags, uint count, uint timeout) {
var fi = new FLASHWINFO {hwnd = handle, dwFlags = flags, uCount = count, dwTimeout = timeout};
fi.cbSize = Convert.ToUInt32(Marshal.SizeOf(fi));
return fi;
}
public bool Flash() {
try {
if (!WindowHandle.handle.valueOut(out var handle)) return false;
var fi = Create_FLASHWINFO(handle, FLASHW_ALL | FLASHW_TIMERNOFG, uint.MaxValue, 0);
return FlashWindowEx(ref fi);
}
catch (Exception e) {
log.error(nameof(Flash), e);
}
return false;
}
public bool Flash(uint count) {
try {
if (!WindowHandle.handle.valueOut(out var handle)) return false;
var fi = Create_FLASHWINFO(handle, FLASHW_ALL, count, 0);
return FlashWindowEx(ref fi);
}
catch (Exception e) {
log.error($"{nameof(Flash)}({count})", e);
}
return false;
}
public bool Start() {
try {
if (!WindowHandle.handle.valueOut(out var handle)) return false;
var fi = Create_FLASHWINFO(handle, FLASHW_ALL, uint.MaxValue, 0);
return FlashWindowEx(ref fi);
}
catch (Exception e) {
log.error(nameof(Start), e);
}
return false;
}
public bool Stop() {
try {
if (!WindowHandle.handle.valueOut(out var handle)) return false;
var fi = Create_FLASHWINFO(handle, FLASHW_STOP, uint.MaxValue, 0);
return FlashWindowEx(ref fi);
}
catch (Exception e) {
log.error(nameof(Stop), e);
}
return false;
}
}
}
#endif
// See Utilities.SetWindowTitle.cs for explanation.
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && !UNITY_EDITOR)
using System.Text;
using System;
using System.Runtime.InteropServices;
using JetBrains.Annotations;
namespace FPCSharpUnity.unity.win32_api {
[PublicAPI] public static class Win32API {
/// Only returns the window if it is currently focused. Otherwise returns <see cref="IntPtr.Zero"/>.
[DllImport("User32.dll")]
public static extern IntPtr GetActiveWindow();
/// <summary>
/// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
/// </summary>
[DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int SendMessage(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool FlashWindowEx(ref FLASHWINFO pwfi);
/// <summary>
/// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentthreadid
/// </summary>
[DllImport("kernel32.dll")]
public static extern uint GetCurrentThreadId();
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
/// <summary>
/// To continue enumeration, the callback function must return TRUE; to stop enumeration, it must return FALSE.
/// </summary>
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
/// <summary>
/// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumthreadwindows
/// </summary>
/// <param name="dwThreadId">Thread ID obtained from <see cref="GetCurrentThreadId"/></param>
/// <param name="lpEnumFunc"></param>
/// <param name="lParam">An application-defined value to be passed to the callback function.</param>
/// <returns>
/// If the callback function returns TRUE for all windows in the thread specified by dwThreadId, the return value
/// is TRUE. If the callback function returns FALSE on any enumerated window, or if there are no windows found in
/// the thread specified by dwThreadId, the return value is FALSE.
/// </returns>
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumThreadWindows(uint dwThreadId, EnumWindowsProc lpEnumFunc, IntPtr lParam);
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment