mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-10 00:48:23 -06:00
Dramatically simplify Icon
This commit is contained in:
parent
7055b99acc
commit
79cf5e2c74
@ -259,23 +259,18 @@ static UINT ConExtractIconInBothSizesW(PCWSTR szFileName, int nIconIndex, HICON*
|
||||
}
|
||||
// Excerpted Region Ends
|
||||
|
||||
Icon::Icon() :
|
||||
_fInitialized(false),
|
||||
_hDefaultIcon(nullptr),
|
||||
_hDefaultSmIcon(nullptr),
|
||||
_hIcon(nullptr),
|
||||
_hSmIcon(nullptr)
|
||||
Icon::Icon()
|
||||
{
|
||||
}
|
||||
|
||||
Icon::~Icon()
|
||||
{
|
||||
// Do not destroy icon handles. They're shared icons as they were loaded from LoadIcon/LoadImage.
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648063(v=vs.85).aspx
|
||||
|
||||
// Do destroy icons from ExtractIconEx. They're not shared.
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648069(v=vs.85).aspx
|
||||
_DestroyNonDefaultIcons();
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4302) // typecast warning from MAKEINTRESOURCE
|
||||
_hDefaultIcon = LoadIconW(nullptr, MAKEINTRESOURCE(IDI_APPLICATION));
|
||||
_hDefaultSmIcon = (HICON)LoadImageW(nullptr,
|
||||
MAKEINTRESOURCE(IDI_APPLICATION),
|
||||
IMAGE_ICON,
|
||||
GetSystemMetrics(SM_CXSMICON),
|
||||
GetSystemMetrics(SM_CYSMICON),
|
||||
LR_SHARED);
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
@ -299,62 +294,33 @@ Icon& Icon::Instance()
|
||||
// - S_OK or HRESULT failure code.
|
||||
[[nodiscard]] HRESULT Icon::GetIcons(_Out_opt_ HICON* const phIcon, _Out_opt_ HICON* const phSmIcon)
|
||||
{
|
||||
auto hr = S_OK;
|
||||
|
||||
if (nullptr != phIcon)
|
||||
if (phIcon)
|
||||
{
|
||||
hr = _GetAvailableIconFromReference(_hIcon, _hDefaultIcon, phIcon);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (nullptr != phSmIcon)
|
||||
*phIcon = _hIcon.get();
|
||||
if (!*phIcon)
|
||||
{
|
||||
hr = _GetAvailableIconFromReference(_hSmIcon, _hDefaultSmIcon, phSmIcon);
|
||||
*phIcon = _hDefaultIcon;
|
||||
}
|
||||
if (!*phIcon)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Sets custom icons onto the class or resets the icons to defaults. Use a null handle to reset an icon to its default value.
|
||||
// Arguments:
|
||||
// - hIcon - The large icon handle or null to reset to default
|
||||
// - hSmIcon - The small icon handle or null to reset to default
|
||||
// Return Value:
|
||||
// - S_OK or HRESULT failure code.
|
||||
[[nodiscard]] HRESULT Icon::SetIcons(const HICON hIcon, const HICON hSmIcon)
|
||||
{
|
||||
auto hr = _SetIconFromReference(_hIcon, hIcon);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
if (phSmIcon)
|
||||
{
|
||||
hr = _SetIconFromReference(_hSmIcon, hSmIcon);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
HICON hNewIcon;
|
||||
HICON hNewSmIcon;
|
||||
|
||||
hr = GetIcons(&hNewIcon, &hNewSmIcon);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
*phSmIcon = _hSmIcon.get();
|
||||
if (!*phSmIcon)
|
||||
{
|
||||
// Special case. If we had a non-default big icon and a default small icon, set the small icon to null when updating the window.
|
||||
// This will cause the large one to be stretched and used as the small one.
|
||||
if (hNewIcon != _hDefaultIcon && hNewSmIcon == _hDefaultSmIcon)
|
||||
{
|
||||
hNewSmIcon = nullptr;
|
||||
}
|
||||
|
||||
PostMessageW(ServiceLocator::LocateConsoleWindow()->GetWindowHandle(), WM_SETICON, ICON_BIG, (LPARAM)hNewIcon);
|
||||
PostMessageW(ServiceLocator::LocateConsoleWindow()->GetWindowHandle(), WM_SETICON, ICON_SMALL, (LPARAM)hNewSmIcon);
|
||||
*phSmIcon = _hDefaultSmIcon;
|
||||
}
|
||||
if (!*phIcon)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
@ -373,10 +339,10 @@ Icon& Icon::Instance()
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648069(v=vs.85).aspx
|
||||
ConExtractIconInBothSizesW(pwszIconLocation, nIconIndex, &_hIcon, &_hSmIcon);
|
||||
|
||||
// If the large icon failed, then ensure that we use the defaults.
|
||||
if (_hIcon == nullptr)
|
||||
// If the large icon failed, clear the other one as well.
|
||||
if (!_hIcon)
|
||||
{
|
||||
_DestroyNonDefaultIcons(); // ensure handles are destroyed/null
|
||||
_hSmIcon.reset();
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
@ -394,182 +360,12 @@ Icon& Icon::Instance()
|
||||
// - S_OK or HRESULT failure code.
|
||||
[[nodiscard]] HRESULT Icon::ApplyWindowMessageWorkaround(const HWND hwnd)
|
||||
{
|
||||
HICON hIcon;
|
||||
HICON hSmIcon;
|
||||
HICON hIcon, hSmIcon;
|
||||
|
||||
auto hr = GetIcons(&hIcon, &hSmIcon);
|
||||
RETURN_IF_FAILED(GetIcons(&hIcon, &hSmIcon));
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
SendMessageW(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
|
||||
SendMessageW(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hSmIcon);
|
||||
}
|
||||
SendMessageW(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
|
||||
SendMessageW(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hSmIcon);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Initializes the icon class by loading the default icons.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - S_OK or HRESULT failure code.
|
||||
[[nodiscard]] HRESULT Icon::_Initialize()
|
||||
{
|
||||
auto hr = S_OK;
|
||||
|
||||
if (!_fInitialized)
|
||||
{
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4302) // typecast warning from MAKEINTRESOURCE
|
||||
_hDefaultIcon = LoadIconW(nullptr, MAKEINTRESOURCE(IDI_APPLICATION));
|
||||
#pragma warning(pop)
|
||||
|
||||
if (_hDefaultIcon == nullptr)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4302) // typecast warning from MAKEINTRESOURCE
|
||||
_hDefaultSmIcon = (HICON)LoadImageW(nullptr,
|
||||
MAKEINTRESOURCE(IDI_APPLICATION),
|
||||
IMAGE_ICON,
|
||||
GetSystemMetrics(SM_CXSMICON),
|
||||
GetSystemMetrics(SM_CYSMICON),
|
||||
LR_SHARED);
|
||||
#pragma warning(pop)
|
||||
|
||||
if (_hDefaultSmIcon == nullptr)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
_fInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Frees any non-default icon handles we may have loaded from a path on the file system
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Icon::_DestroyNonDefaultIcons()
|
||||
{
|
||||
_FreeIconFromReference(_hIcon);
|
||||
_FreeIconFromReference(_hSmIcon);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Helper method to choose one of the two given references to fill the pointer with.
|
||||
// - It will choose the specific icon if it is available and otherwise fall back to the default icon.
|
||||
// Arguments:
|
||||
// - hIconRef - reference to the specific icon handle inside this class
|
||||
// - hDefaultIconRef - reference to the default icon handle inside this class
|
||||
// - phIcon - pointer to receive the chosen icon handle
|
||||
// Return Value:
|
||||
// - S_OK or HRESULT failure code.
|
||||
[[nodiscard]] HRESULT Icon::_GetAvailableIconFromReference(_In_ HICON& hIconRef, _In_ HICON& hDefaultIconRef, _Out_ HICON* const phIcon)
|
||||
{
|
||||
auto hr = S_OK;
|
||||
|
||||
// expecting hIconRef to be pointing to either the regular or small custom handles
|
||||
FAIL_FAST_IF(!(&hIconRef == &_hIcon || &hIconRef == &_hSmIcon));
|
||||
|
||||
// expecting hDefaultIconRef to be pointing to either the regular or small default handles
|
||||
FAIL_FAST_IF(!(&hDefaultIconRef == &_hDefaultIcon || &hDefaultIconRef == &_hDefaultSmIcon));
|
||||
|
||||
if (hIconRef != nullptr)
|
||||
{
|
||||
*phIcon = hIconRef;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = _GetDefaultIconFromReference(hDefaultIconRef, phIcon);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Helper method to initialize and retrieve a default icon.
|
||||
// Arguments:
|
||||
// - hIconRef - Either the small or large icon handle references within this class
|
||||
// - phIcon - The pointer to fill with the icon if it is available.
|
||||
// Return Value:
|
||||
// - S_OK or HRESULT failure code.
|
||||
[[nodiscard]] HRESULT Icon::_GetDefaultIconFromReference(_In_ HICON& hIconRef, _Out_ HICON* const phIcon)
|
||||
{
|
||||
// expecting hIconRef to be pointing to either the regular or small default handles
|
||||
FAIL_FAST_IF(!(&hIconRef == &_hDefaultIcon || &hIconRef == &_hDefaultSmIcon));
|
||||
|
||||
auto hr = _Initialize();
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
*phIcon = hIconRef;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Helper method to set an icon handle into the given reference to an icon within this class.
|
||||
// - This will appropriately call to free existing custom icons.
|
||||
// Arguments:
|
||||
// - hIconRef - Either the small or large icon handle references within this class
|
||||
// - hNewIcon - The new icon handle to replace the reference with.
|
||||
// Return Value:
|
||||
// - S_OK or HRESULT failure code.
|
||||
[[nodiscard]] HRESULT Icon::_SetIconFromReference(_In_ HICON& hIconRef, const HICON hNewIcon)
|
||||
{
|
||||
// expecting hIconRef to be pointing to either the regular or small custom handles
|
||||
FAIL_FAST_IF(!(&hIconRef == &_hIcon || &hIconRef == &_hSmIcon));
|
||||
|
||||
auto hr = S_OK;
|
||||
|
||||
// Only set icon if something changed
|
||||
if (hNewIcon != hIconRef)
|
||||
{
|
||||
// If we had an existing custom icon, free it.
|
||||
_FreeIconFromReference(hIconRef);
|
||||
|
||||
// If we were given a non-null icon, store it.
|
||||
if (hNewIcon != nullptr)
|
||||
{
|
||||
hIconRef = hNewIcon;
|
||||
}
|
||||
|
||||
// Otherwise, we'll default back to using the default icon. Get method will handle this.
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Helper method to free a specific icon reference to a specific icon within this class.
|
||||
// - WARNING: Do not use with the default icons. They do not need to be released.
|
||||
// Arguments:
|
||||
// - hIconRef - Either the small or large specific icon handle references within this class
|
||||
// Return Value:
|
||||
// - None
|
||||
void Icon::_FreeIconFromReference(_In_ HICON& hIconRef)
|
||||
{
|
||||
// expecting hIconRef to be pointing to either the regular or small custom handles
|
||||
FAIL_FAST_IF(!(&hIconRef == &_hIcon || &hIconRef == &_hSmIcon));
|
||||
|
||||
if (hIconRef != nullptr)
|
||||
{
|
||||
DestroyIcon(hIconRef);
|
||||
hIconRef = nullptr;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -23,33 +23,21 @@ namespace Microsoft::Console::Interactivity::Win32
|
||||
static Icon& Instance();
|
||||
|
||||
[[nodiscard]] HRESULT GetIcons(_Out_opt_ HICON* const phIcon, _Out_opt_ HICON* const phSmIcon);
|
||||
[[nodiscard]] HRESULT SetIcons(const HICON hIcon, const HICON hSmIcon);
|
||||
|
||||
[[nodiscard]] HRESULT LoadIconsFromPath(_In_ PCWSTR pwszIconLocation, const int nIconIndex);
|
||||
|
||||
[[nodiscard]] HRESULT ApplyWindowMessageWorkaround(const HWND hwnd);
|
||||
|
||||
protected:
|
||||
Icon();
|
||||
~Icon();
|
||||
~Icon() = default;
|
||||
Icon(const Icon&) = delete;
|
||||
void operator=(const Icon&) = delete;
|
||||
|
||||
private:
|
||||
[[nodiscard]] HRESULT _Initialize();
|
||||
// We are not using unique_hicon for these, as they are loaded from our mapped executable image.
|
||||
HICON _hDefaultIcon{ nullptr };
|
||||
HICON _hDefaultSmIcon{ nullptr };
|
||||
|
||||
void _DestroyNonDefaultIcons();
|
||||
|
||||
// Helper methods
|
||||
[[nodiscard]] HRESULT _GetAvailableIconFromReference(_In_ HICON& hIconRef, _In_ HICON& hDefaultIconRef, _Out_ HICON* const phIcon);
|
||||
[[nodiscard]] HRESULT _GetDefaultIconFromReference(_In_ HICON& hIconRef, _Out_ HICON* const phIcon);
|
||||
[[nodiscard]] HRESULT _SetIconFromReference(_In_ HICON& hIconRef, const HICON hNewIcon);
|
||||
void _FreeIconFromReference(_In_ HICON& hIconRef);
|
||||
|
||||
bool _fInitialized;
|
||||
HICON _hDefaultIcon;
|
||||
HICON _hDefaultSmIcon;
|
||||
HICON _hIcon;
|
||||
HICON _hSmIcon;
|
||||
wil::unique_hicon _hIcon;
|
||||
wil::unique_hicon _hSmIcon;
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user