So I also wasn't able to repro with my code example on my Windows 11 23H2 laptop, but the following reproduced the issue I'm describing. Basically whatever the icon set in the HWND overrides AudioSessionControl::SetIconPath, except for SndVol. I expect SetIconPath to take priority in volume mixer applications.
The red icon is what I set to the HWND, the grey animal one is what I set to the AudioSessionControl::SetIconPath.
In this code snippet, I added a HWND
#include <windows.h>
#include <mmdeviceapi.h>
#include <audioclient.h>
#include <audiopolicy.h>
#include <comdef.h>
#include <iostream>
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "Mmdevapi.lib")
// Window procedure callback
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
int main()
{
CoInitialize(nullptr);
HRESULT hr = S_OK;
IMMDeviceEnumerator* pDeviceEnumerator = nullptr;
IMMDevice* pDevice = nullptr;
IAudioClient* pAudioClient = nullptr;
IAudioSessionControl* pAudioSessionControl = nullptr;
REFERENCE_TIME hnsRequestedDuration = 10000000; // 1 second
WAVEFORMATEX* pwfx = nullptr;
hr = CoCreateInstance(
__uuidof(MMDeviceEnumerator),
nullptr,
CLSCTX_ALL,
__uuidof(IMMDeviceEnumerator),
(void**)&pDeviceEnumerator);
if (FAILED(hr)) {
std::cerr << "Failed to create device enumerator: " << _com_error(hr).ErrorMessage() << std::endl;
CoUninitialize();
return hr;
}
hr = pDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
if (FAILED(hr)) {
std::cerr << "Failed to get default audio endpoint: " << _com_error(hr).ErrorMessage() << std::endl;
pDeviceEnumerator->Release();
CoUninitialize();
return hr;
}
hr = pDevice->Activate(
__uuidof(IAudioClient),
CLSCTX_ALL,
nullptr,
(void**)&pAudioClient);
if (FAILED(hr)) {
std::cerr << "Failed to activate audio client: " << _com_error(hr).ErrorMessage() << std::endl;
pDevice->Release();
pDeviceEnumerator->Release();
CoUninitialize();
return hr;
}
hr = pAudioClient->GetMixFormat(&pwfx);
if (FAILED(hr)) {
std::cerr << "Failed to get mix format: " << _com_error(hr).ErrorMessage() << std::endl;
pAudioClient->Release();
pDevice->Release();
pDeviceEnumerator->Release();
CoUninitialize();
return hr;
}
hr = pAudioClient->Initialize(
AUDCLNT_SHAREMODE_SHARED,
0, // No stream flags
hnsRequestedDuration,
0,
pwfx,
nullptr);
if (FAILED(hr)) {
std::cerr << "Failed to initialize audio client: " << _com_error(hr).ErrorMessage() << std::endl;
CoTaskMemFree(pwfx);
pAudioClient->Release();
pDevice->Release();
pDeviceEnumerator->Release();
CoUninitialize();
return hr;
}
hr = pAudioClient->GetService(__uuidof(IAudioSessionControl), (void**)&pAudioSessionControl);
if (FAILED(hr)) {
std::cerr << "Failed to get audio session control: " << _com_error(hr).ErrorMessage() << std::endl;
pAudioClient->Release();
pDevice->Release();
pDeviceEnumerator->Release();
CoUninitialize();
return hr;
}
// Please replace this with whatever icon you have.
//LPCWSTR iconPath = L"C:\\Users\\rizhang\\source\\repos\\VolumeIconIssue\\VolumeIconIssue\\testicon.ico";
LPCWSTR iconPath = L"C:\\Users\\rizha\\Downloads\\testicon.ico";
hr = pAudioSessionControl->SetIconPath(iconPath, nullptr);
if (FAILED(hr)) {
std::cerr << "Failed to set icon path: " << _com_error(hr).ErrorMessage() << std::endl;
}
else {
std::cout << "Icon path set successfully!" << std::endl;
}
const wchar_t CLASS_NAME[] = L"Sample Window Class";
HINSTANCE hInstance = GetModuleHandle(nullptr);
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(
0,
CLASS_NAME,
L"My Audio Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
nullptr,
nullptr,
hInstance,
nullptr
);
if (hwnd == nullptr) {
std::cerr << "Failed to create window." << std::endl;
CoTaskMemFree(pwfx);
pAudioSessionControl->Release();
pAudioClient->Release();
pDevice->Release();
pDeviceEnumerator->Release();
CoUninitialize();
return -1;
}
HICON hIcon = static_cast<HICON>(LoadImage(
nullptr,
L"C:\\Users\\rizha\\Downloads\\hwndicon.ico",
IMAGE_ICON,
32, 32,
LR_LOADFROMFILE | LR_SHARED
));
if (hIcon != nullptr) {
// The icon set here overrides the icon set in in AudioSessionControl::SetIconPath.
SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
}
else {
std::cerr << "Failed to load window icon." << std::endl;
}
ShowWindow(hwnd, SW_SHOW);
MSG msg = {};
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
std::cout << "Press enter to exit..." << std::endl;
std::cin.get(); // Pauses the program until the user presses Enter
pAudioSessionControl->Release();
pAudioClient->Release();
pDevice->Release();
pDeviceEnumerator->Release();
CoUninitialize();
return hr;
}