Skip to content

Conversation

@georgiai1
Copy link

@georgiai1 georgiai1 commented Jan 13, 2026

● Summary

Add audio-scroll-switcher mod to switch audio output devices with Ctrl+Scroll on the taskbar.
Displays a Windows 11-style notification popup showing the active device.
Strips parenthetical text from device names for cleaner display.

How it works

  • Subclasses the taskbar window to intercept mouse wheel messages.
  • Hooks Windows 11 XAML InputSite for modern taskbar support.
  • Uses IPolicyConfig (undocumented COM interface) to set default audio endpoint.
  • Sets all audio roles (Console, Multimedia, Communications) when switching.

Testing

  • ☑ Manual: Ctrl+Scroll on taskbar cycles through audio devices.
  • ☑ Manual: Notification popup appears with device name (no parenthetical text).
  • ☑ Manual: Works on primary and secondary taskbars (multi-monitor).
  • ☑ Manual: Works on Windows 10 and Windows 11 taskbars.

Copy link
Member

@m417z m417z left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice mod, well done!

}

if (g_popupWnd) {
DestroyWindow(g_popupWnd);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the documentation:

A thread cannot use DestroyWindow to destroy a window created by a different thread.

Use SendMessage to close it instead. Currently it won't work, and if the mod is unloaded while the popup is open, it will cause a crash.

g_popupClassRegistered = false;
}

CoUninitialize();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might run in a different thread than CoInitializeEx. See: https://github.com/ramensoftware/windhawk/wiki/Mod-lifetime

You can just run CoUninitialize in Wh_ModInit, since it's only needed for GetAudioOutputDevices.

WNDCLASSEXW wc = {0};
wc.cbSize = sizeof(WNDCLASSEXW);
wc.lpfnWndProc = PopupWndProc;
wc.hInstance = GetModuleHandle(nullptr);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to use the mod dll instance. You can use this function:

HMODULE GetCurrentModuleHandle() {
HMODULE module;
if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
L"", &module)) {
return nullptr;
}
return module;
}


Wh_Log(L"Ctrl+Scroll detected! delta=%d, direction=%d", delta, direction);

SwitchAudioDevice(direction);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to add a throttle (e.g. process at most one message each 400 milliseconds), since some sensitive mice send several messages with a small delta each.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants