1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

HWNDComponentPeer: Fix icon leaks

Co-authored-by: ValentynPavliuchenkoA <valentyn.pavliuchenko@avid.com>
This commit is contained in:
reuk 2022-10-06 17:47:19 +01:00
parent d8301ddc1c
commit 59a47a4638
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
2 changed files with 39 additions and 37 deletions

View file

@ -42,7 +42,7 @@ WinRTWrapper::WinRTWrapper()
return;
HRESULT status = roInitialize (1);
initialised = ! (status != S_OK && status != S_FALSE && status != 0x80010106L);
initialised = ! (status != S_OK && status != S_FALSE && status != (HRESULT) 0x80010106L);
}
WinRTWrapper::~WinRTWrapper()

View file

@ -1113,6 +1113,13 @@ Image createSnapshotOfNativeWindow (void* nativeWindowHandle)
//==============================================================================
namespace IconConverters
{
struct IconDestructor
{
void operator() (HICON ptr) const { if (ptr != nullptr) DestroyIcon (ptr); }
};
using IconPtr = std::unique_ptr<std::remove_pointer_t<HICON>, IconDestructor>;
static Image createImageFromHICON (HICON icon)
{
if (icon == nullptr)
@ -1675,9 +1682,6 @@ public:
callFunctionIfNotLocked (&destroyWindowCallback, (void*) hwnd);
if (currentWindowIcon != nullptr)
DestroyIcon (currentWindowIcon);
if (dropTarget != nullptr)
{
dropTarget->peerIsDeleted = true;
@ -2315,7 +2319,7 @@ private:
bool fullScreen = false, isDragging = false, isMouseOver = false,
hasCreatedCaret = false, constrainerIsResizing = false;
BorderSize<int> windowBorder;
HICON currentWindowIcon = nullptr;
IconConverters::IconPtr currentWindowIcon;
FileDropTarget* dropTarget = nullptr;
uint8 updateLayeredWindowAlpha = 255;
UWPUIViewSettings uwpViewSettings;
@ -2377,7 +2381,6 @@ private:
TCHAR moduleFile[1024] = {};
GetModuleFileName (moduleHandle, moduleFile, 1024);
WORD iconNum = 0;
WNDCLASSEX wcex = {};
wcex.cbSize = sizeof (wcex);
@ -2386,9 +2389,13 @@ private:
wcex.lpszClassName = windowClassName.toWideCharPointer();
wcex.cbWndExtra = 32;
wcex.hInstance = moduleHandle;
wcex.hIcon = ExtractAssociatedIcon (moduleHandle, moduleFile, &iconNum);
iconNum = 1;
wcex.hIconSm = ExtractAssociatedIcon (moduleHandle, moduleFile, &iconNum);
for (const auto& [index, field, ptr] : { std::tuple { 0, &wcex.hIcon, &iconBig },
std::tuple { 1, &wcex.hIconSm, &iconSmall } })
{
auto iconNum = static_cast<WORD> (index);
ptr->reset (*field = ExtractAssociatedIcon (moduleHandle, moduleFile, &iconNum));
}
atom = RegisterClassEx (&wcex);
jassert (atom != 0);
@ -2483,6 +2490,8 @@ private:
return false;
}
IconConverters::IconPtr iconBig, iconSmall;
JUCE_DECLARE_NON_COPYABLE (WindowClassHolder)
};
@ -2668,15 +2677,11 @@ private:
void setIcon (const Image& newIcon) override
{
if (auto hicon = IconConverters::createHICONFromImage (newIcon, TRUE, 0, 0))
if (IconConverters::IconPtr hicon { IconConverters::createHICONFromImage (newIcon, TRUE, 0, 0) })
{
SendMessage (hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
SendMessage (hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
if (currentWindowIcon != nullptr)
DestroyIcon (currentWindowIcon);
currentWindowIcon = hicon;
SendMessage (hwnd, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM> (hicon.get()));
SendMessage (hwnd, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM> (hicon.get()));
currentWindowIcon = std::move (hicon);
}
}
@ -5367,27 +5372,23 @@ void Displays::findDisplays (float masterScale)
}
//==============================================================================
static HICON extractFileHICON (const File& file)
static auto extractFileHICON (const File& file)
{
WORD iconNum = 0;
WCHAR name[MAX_PATH * 2];
file.getFullPathName().copyToUTF16 (name, sizeof (name));
return ExtractAssociatedIcon ((HINSTANCE) Process::getCurrentModuleInstanceHandle(),
name, &iconNum);
return IconConverters::IconPtr { ExtractAssociatedIcon ((HINSTANCE) Process::getCurrentModuleInstanceHandle(),
name,
&iconNum) };
}
Image juce_createIconForFile (const File& file)
{
Image image;
if (const auto icon = extractFileHICON (file))
return IconConverters::createImageFromHICON (icon.get());
if (auto icon = extractFileHICON (file))
{
image = IconConverters::createImageFromHICON (icon);
DestroyIcon (icon);
}
return image;
return {};
}
//==============================================================================
@ -5435,12 +5436,6 @@ private:
public:
explicit ImageImpl (const CustomMouseCursorInfo& infoIn) : info (infoIn) {}
~ImageImpl() override
{
for (auto& pair : cursorsBySize)
DestroyCursor (pair.second);
}
HCURSOR getCursor (ComponentPeer& peer) override
{
JUCE_ASSERT_MESSAGE_THREAD;
@ -5451,7 +5446,7 @@ private:
const auto iter = cursorsBySize.find (size);
if (iter != cursorsBySize.end())
return iter->second;
return iter->second.get();
const auto logicalSize = info.image.getScaledBounds();
const auto scale = (float) size / (float) unityCursorSize;
@ -5466,12 +5461,19 @@ private:
const auto hx = jlimit (0, rescaled.getWidth(), roundToInt ((float) info.hotspot.x * effectiveScale));
const auto hy = jlimit (0, rescaled.getHeight(), roundToInt ((float) info.hotspot.y * effectiveScale));
return cursorsBySize.emplace (size, IconConverters::createHICONFromImage (rescaled, false, hx, hy)).first->second;
return cursorsBySize.emplace (size, CursorPtr { IconConverters::createHICONFromImage (rescaled, false, hx, hy) }).first->second.get();
}
private:
struct CursorDestructor
{
void operator() (HCURSOR ptr) const { if (ptr != nullptr) DestroyCursor (ptr); }
};
using CursorPtr = std::unique_ptr<std::remove_pointer_t<HCURSOR>, CursorDestructor>;
const CustomMouseCursorInfo info;
std::map<int, HCURSOR> cursorsBySize;
std::map<int, CursorPtr> cursorsBySize;
};
static auto getCursorSizeForPeerFunction() -> int (*) (ComponentPeer&)