diff --git a/windows/cc/WindowWin32.cc b/windows/cc/WindowWin32.cc index 4c138013..3e4cbeae 100644 --- a/windows/cc/WindowWin32.cc +++ b/windows/cc/WindowWin32.cc @@ -129,6 +129,18 @@ void jwm::WindowWin32::setIcon(const std::wstring& iconPath) { SendMessage(_hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hicon); } +void jwm::WindowWin32::setIcon(const unsigned char* iconData, int dataLength) { + // Get the identifier (i.e. offset) of the icon that is most appropriate + // for the current video display + int nID = LookupIconIdFromDirectoryEx(const_cast(reinterpret_cast(iconData)), + TRUE, 0, 0, LR_DEFAULTCOLOR); + if (nID > 0) { + HICON hicon = CreateIconFromResourceEx(const_cast(reinterpret_cast(iconData + nID)), + dataLength - nID, TRUE, 0x00030000, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE); + SendMessage(_hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hicon); + } +} + void jwm::WindowWin32::setOpacity(float opacity) { JWM_VERBOSE("Set window opacity'" << opacity << "'"); LONG_PTR previousStyle = GetWindowLongPtr(_hWnd, GWL_EXSTYLE); @@ -1103,6 +1115,14 @@ extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_jwm_WindowWin32__1nSet env->ReleaseStringChars(iconPath, iconPathStr); } +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_jwm_WindowWin32__1nSetIconData + (JNIEnv* env, jobject obj, jbyteArray iconData, jint dataLength) { + jwm::WindowWin32* instance = reinterpret_cast(jwm::classes::Native::fromJava(env, obj)); + jbyte* bytes = env->GetByteArrayElements(iconData, nullptr); + instance->setIcon(reinterpret_cast(bytes), dataLength); + env->ReleaseByteArrayElements(iconData, bytes, 0); +} + extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_jwm_WindowWin32__1nSetVisible (JNIEnv* env, jobject obj, jboolean isVisible) { jwm::WindowWin32* instance = reinterpret_cast(jwm::classes::Native::fromJava(env, obj)); diff --git a/windows/cc/WindowWin32.hh b/windows/cc/WindowWin32.hh index d35331d0..0fbd948d 100644 --- a/windows/cc/WindowWin32.hh +++ b/windows/cc/WindowWin32.hh @@ -53,6 +53,7 @@ namespace jwm { void setTitle(const std::wstring& title); void setTitlebarVisible(bool isVisible); void setIcon(const std::wstring& iconPath); + void setIcon(const unsigned char* iconData, int dataLength); void setOpacity(float opacity); float getOpacity(); bool isHighContrast(); diff --git a/windows/java/WindowWin32.java b/windows/java/WindowWin32.java index 5548c638..1f968acf 100644 --- a/windows/java/WindowWin32.java +++ b/windows/java/WindowWin32.java @@ -75,6 +75,18 @@ public Window setIcon(File icon){ return this; } + /** + *

Set window icon from raw ICO bytes.

+ * + * @param iconData byte array of raw ICO data + * @return this + */ + public Window setIcon(byte[] iconData) { + assert _onUIThread() : "Should be run on UI thread"; + _nSetIconData(iconData, iconData.length); + return this; + } + @Override public Window setTitlebarVisible(boolean value) { assert _onUIThread(); @@ -228,6 +240,7 @@ public Window winSetParent(long hwnd) { @ApiStatus.Internal public native void _nSetTitle(String title); @ApiStatus.Internal public native void _nSetTitlebarVisible(boolean isVisible); @ApiStatus.Internal public native void _nSetIcon(String iconPath); + @ApiStatus.Internal public native void _nSetIconData(byte[] iconData, int dataLength); @ApiStatus.Internal public native void _nSetVisible(boolean isVisible); @ApiStatus.Internal public native void _nSetOpacity(float opacity); @ApiStatus.Internal public native float _nGetOpacity();