Created
March 18, 2025 16:50
-
-
Save pongo/4ef98cac1f63ecf9785ab139bec8b02c to your computer and use it in GitHub Desktop.
NoFlashWindow for 10 seconds
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==WindhawkMod== | |
// @id no-flash-window-fork | |
// @name NoFlashWindow | |
// @description Prevent programs from flashing their windows on the taskbar | |
// @version 1.0 | |
// @author m417z | |
// @github https://github.com/m417z | |
// @twitter https://twitter.com/m417z | |
// @homepage https://m417z.com/ | |
// @include * | |
// ==/WindhawkMod== | |
// For bug reports and feature requests, please open an issue here: | |
// https://github.com/ramensoftware/windhawk-mods/issues | |
// | |
// For pull requests, development takes place here: | |
// https://github.com/m417z/my-windhawk-mods | |
// ==WindhawkModReadme== | |
/* | |
# NoFlashWindow | |
Prevent programs from flashing their windows on the taskbar. | |
Inspired by [NoFlashWindow](https://github.com/mrexodia/NoFlashWindow) by Duncan | |
Ogilvie. | |
**Note**: Windows 11 seems to have [a native option for | |
this](https://www.elevenforum.com/t/enable-or-disable-show-flashing-on-taskbar-apps-in-windows-11.9968/). | |
 | |
*/ | |
// ==/WindhawkModReadme== | |
// ==WindhawkModSettings== | |
/* | |
- mode: prevent | |
$name: Mode | |
$options: | |
- prevent: Prevent flashing | |
- limitToOne: Limit flashing to one time | |
- limitToTenSeconds: Limit flashing to 10 seconds | |
*/ | |
// ==/WindhawkModSettings== | |
#include <unordered_map> | |
#include <vector> | |
#include <windows.h> | |
enum class Mode { | |
prevent, | |
limitToOne, | |
limitToTenSeconds, | |
}; | |
struct { | |
Mode mode; | |
} g_settings; | |
struct WindowFlashInfo { | |
DWORD startTime; | |
HWND hWnd; | |
}; | |
// Хранит информацию о мигающих окнах и времени начала мигания | |
std::unordered_map<HWND, DWORD> g_flashingWindows; | |
// Таймер для проверки и сброса мигающих окон | |
UINT_PTR g_flashTimer = 0; | |
// Функция обратного вызова для таймера | |
VOID CALLBACK FlashTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { | |
Wh_Log(L"Checking flashing windows timer"); | |
DWORD currentTime = GetTickCount(); | |
std::vector<HWND> windowsToReset; | |
// Проверяем все мигающие окна | |
for (auto it = g_flashingWindows.begin(); it != g_flashingWindows.end(); ++it) { | |
HWND hWnd = it->first; | |
DWORD startTime = it->second; | |
// Если окно мигает более 10 секунд (10000 мс) | |
if (currentTime - startTime > 10000) { | |
windowsToReset.push_back(hWnd); | |
} | |
} | |
// Сбрасываем мигание для окон, которые мигали слишком долго | |
for (HWND hWnd : windowsToReset) { | |
Wh_Log(L"Resetting flash for window after 10 seconds"); | |
FLASHWINFO fwi = {}; | |
fwi.cbSize = sizeof(FLASHWINFO); | |
fwi.hwnd = hWnd; | |
fwi.dwFlags = FLASHW_STOP; | |
FlashWindowEx(&fwi); | |
g_flashingWindows.erase(hWnd); | |
} | |
// Если больше нет мигающих окон, удаляем таймер | |
if (g_flashingWindows.empty() && g_flashTimer != 0) { | |
KillTimer(NULL, g_flashTimer); | |
g_flashTimer = 0; | |
Wh_Log(L"No more flashing windows, killing timer"); | |
} | |
} | |
using FlashWindow_t = decltype(&FlashWindow); | |
FlashWindow_t FlashWindow_Original; | |
BOOL WINAPI FlashWindow_Hook(HWND hWnd, WINBOOL bInvert) { | |
Wh_Log(L"FlashWindow called"); | |
if (g_settings.mode == Mode::prevent) { | |
return TRUE; | |
} | |
if (g_settings.mode == Mode::limitToTenSeconds) { | |
// Записываем время начала мигания | |
if (bInvert) { | |
g_flashingWindows[hWnd] = GetTickCount(); | |
// Создаем таймер, если он еще не создан | |
if (g_flashTimer == 0) { | |
g_flashTimer = SetTimer(NULL, 0, 1000, FlashTimerProc); | |
Wh_Log(L"Created flash timer"); | |
} | |
} | |
} | |
return FlashWindow_Original(hWnd, bInvert); | |
} | |
using FlashWindowEx_t = decltype(&FlashWindowEx); | |
FlashWindowEx_t FlashWindowEx_Original; | |
BOOL WINAPI FlashWindowEx_Hook(PFLASHWINFO pfwi) { | |
Wh_Log(L"FlashWindowEx called"); | |
if (g_settings.mode == Mode::prevent) { | |
return TRUE; | |
} | |
FLASHWINFO newFwi = *pfwi; | |
if (g_settings.mode == Mode::limitToOne) { | |
newFwi.dwFlags &= ~(FLASHW_TIMER | FLASHW_TIMERNOFG); | |
if (newFwi.uCount > 1) { | |
newFwi.uCount = 1; | |
} | |
} | |
else if (g_settings.mode == Mode::limitToTenSeconds) { | |
// Если это не запрос на остановку мигания | |
if (!(pfwi->dwFlags & FLASHW_STOP)) { | |
// Записываем время начала мигания | |
g_flashingWindows[pfwi->hwnd] = GetTickCount(); | |
// Создаем таймер, если он еще не создан | |
if (g_flashTimer == 0) { | |
g_flashTimer = SetTimer(NULL, 0, 1000, FlashTimerProc); | |
Wh_Log(L"Created flash timer for FlashWindowEx"); | |
} | |
} | |
else { | |
// Если это запрос на остановку мигания, удаляем окно из списка | |
g_flashingWindows.erase(pfwi->hwnd); | |
} | |
} | |
return FlashWindowEx_Original(&newFwi); | |
} | |
void LoadSettings() { | |
PCWSTR mode = Wh_GetStringSetting(L"mode"); | |
g_settings.mode = Mode::prevent; | |
if (wcscmp(mode, L"limitToOne") == 0) { | |
g_settings.mode = Mode::limitToOne; | |
} | |
else if (wcscmp(mode, L"limitToTenSeconds") == 0) { | |
g_settings.mode = Mode::limitToTenSeconds; | |
} | |
Wh_FreeStringSetting(mode); | |
} | |
BOOL Wh_ModInit() { | |
Wh_Log(L"Mod initializing"); | |
LoadSettings(); | |
Wh_SetFunctionHook((void*)FlashWindow, (void*)FlashWindow_Hook, | |
(void**)&FlashWindow_Original); | |
Wh_SetFunctionHook((void*)FlashWindowEx, (void*)FlashWindowEx_Hook, | |
(void**)&FlashWindowEx_Original); | |
return TRUE; | |
} | |
void Wh_ModUninit() { | |
Wh_Log(L"Mod unloading"); | |
// Удаляем таймер при выгрузке мода | |
if (g_flashTimer != 0) { | |
KillTimer(NULL, g_flashTimer); | |
g_flashTimer = 0; | |
} | |
// Очищаем список мигающих окон | |
g_flashingWindows.clear(); | |
} | |
void Wh_ModSettingsChanged() { | |
Wh_Log(L"Settings changed"); | |
LoadSettings(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment