Skip to content

Commit 155edf9

Browse files
committed
Improve Program icons scaling for win32 #62
This commit implements scaling of program icons by retrieving it from SHDefExtractIcon, which also provides the system default icons for the file type followed by a fallback if the pszFile for the icon is not valid. The fallback uses the extension to retrieve the icon using SHGetFileInfo in small and large size and scales it accordingly with the required zoom level. contributes to #62 and #127
1 parent 857ac0b commit 155edf9

File tree

6 files changed

+66
-28
lines changed

6 files changed

+66
-28
lines changed

bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7498,6 +7498,28 @@ JNIEXPORT jint JNICALL OS_NATIVE(SHDRAGIMAGE_1sizeof)
74987498
}
74997499
#endif
75007500

7501+
#ifndef NO_SHDefExtractIcon
7502+
JNIEXPORT jint JNICALL OS_NATIVE(SHDefExtractIcon)
7503+
(JNIEnv *env, jclass that, jcharArray arg0, jint arg1, jint arg2, jlongArray arg3, jlongArray arg4, jint arg5)
7504+
{
7505+
jchar *lparg0=NULL;
7506+
jlong *lparg3=NULL;
7507+
jlong *lparg4=NULL;
7508+
jint rc = 0;
7509+
OS_NATIVE_ENTER(env, that, SHDefExtractIcon_FUNC);
7510+
if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
7511+
if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
7512+
if (arg4) if ((lparg4 = (*env)->GetLongArrayElements(env, arg4, NULL)) == NULL) goto fail;
7513+
rc = (jint)SHDefExtractIcon((LPWSTR)lparg0, arg1, arg2, (HICON FAR *)lparg3, (HICON FAR *)lparg4, arg5);
7514+
fail:
7515+
if (arg4 && lparg4) (*env)->ReleaseLongArrayElements(env, arg4, lparg4, 0);
7516+
if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
7517+
if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
7518+
OS_NATIVE_EXIT(env, that, SHDefExtractIcon_FUNC);
7519+
return rc;
7520+
}
7521+
#endif
7522+
75017523
#ifndef NO_SHELLEXECUTEINFO_1sizeof
75027524
JNIEXPORT jint JNICALL OS_NATIVE(SHELLEXECUTEINFO_1sizeof)
75037525
(JNIEnv *env, jclass that)

bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ typedef enum {
567567
SCROLLBARINFO_1sizeof_FUNC,
568568
SCROLLINFO_1sizeof_FUNC,
569569
SHDRAGIMAGE_1sizeof_FUNC,
570+
SHDefExtractIcon_FUNC,
570571
SHELLEXECUTEINFO_1sizeof_FUNC,
571572
SHFILEINFO_1sizeof_FUNC,
572573
SHGetFileInfo_FUNC,

bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_structs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2022 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0

bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_structs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2021 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0

bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4445,6 +4445,16 @@ public static int HRESULT_FROM_WIN32(int x) {
44454445
* @param lpXform cast=(XFORM *),flags=no_out
44464446
*/
44474447
public static final native boolean SetWorldTransform(long hdc, float[] lpXform);
4448+
/**
4449+
* @param lpszFile cast=(LPWSTR)
4450+
* @param phiconLarge cast=(HICON FAR *)
4451+
* @param phiconSmall cast=(HICON FAR *)
4452+
*/
4453+
public static final native int SHDefExtractIcon (char [] lpszFile, int iIndex, int uFlags, long [] phiconLarge, long [] phiconSmall, int nIconSize);
4454+
public static final int SHDefExtractIcon (TCHAR lpszFile, int iIndex, int uFlags, long [] phiconLarge, long [] phiconSmall, int nIconSize) {
4455+
char [] lpszFile1 = lpszFile == null ? null : lpszFile.chars;
4456+
return SHDefExtractIcon (lpszFile1, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
4457+
}
44484458
/** @param pszPath cast=(LPCWSTR),flags=no_out */
44494459
public static final native long SHGetFileInfo (char [] pszPath, int dwFileAttributes, SHFILEINFO psfi, int cbFileInfo, int uFlags);
44504460
public static final native boolean ShellExecuteEx (SHELLEXECUTEINFO lpExecInfo);

bundles/org.eclipse.swt/Eclipse SWT Program/win32/org/eclipse/swt/program/Program.java

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -379,28 +379,6 @@ public ImageData getImageData () {
379379
* @since 3.125
380380
*/
381381
public ImageData getImageData (int zoom) {
382-
// OS.SHGetFileInfo is System DPI-aware, hence it retrieves the icon with zoom
383-
// of primary monitor at the application startup
384-
int initialNativeZoom = getPrimaryMonitorZoomAtStartup();
385-
if (extension != null) {
386-
SHFILEINFO shfi = new SHFILEINFO ();
387-
int flags = OS.SHGFI_ICON | OS.SHGFI_USEFILEATTRIBUTES;
388-
boolean useLargeIcon = 100 * zoom / initialNativeZoom >= 200;
389-
if(useLargeIcon) {
390-
flags |= OS.SHGFI_LARGEICON;
391-
initialNativeZoom *= 2;
392-
} else {
393-
flags |= OS.SHGFI_SMALLICON;
394-
}
395-
TCHAR pszPath = new TCHAR (0, extension, true);
396-
OS.SHGetFileInfo (pszPath.chars, OS.FILE_ATTRIBUTE_NORMAL, shfi, SHFILEINFO.sizeof, flags);
397-
if (shfi.hIcon != 0) {
398-
Image image = Image.win32_new (null, SWT.ICON, shfi.hIcon, initialNativeZoom);
399-
ImageData imageData = image.getImageData (zoom);
400-
image.dispose ();
401-
return imageData;
402-
}
403-
}
404382
int nIconIndex = 0;
405383
String fileName = iconName;
406384
int index = iconName.indexOf (',');
@@ -418,15 +396,42 @@ public ImageData getImageData (int zoom) {
418396
}
419397
}
420398
TCHAR lpszFile = new TCHAR (0, fileName, true);
421-
long [] phiconSmall = new long[1], phiconLarge = null;
422-
OS.ExtractIconEx (lpszFile, nIconIndex, phiconLarge, phiconSmall, 1);
423-
if (phiconSmall [0] == 0) return null;
424-
Image image = Image.win32_new (null, SWT.ICON, phiconSmall [0], initialNativeZoom);
399+
long [] hIcon = new long[1];
400+
int size = OS.GetSystemMetricsForDpi(OS.SM_CXSMICON, DPIUtil.mapZoomToDPI(zoom));
401+
OS.SHDefExtractIcon (lpszFile, nIconIndex, 0, hIcon, null, size);
402+
if (hIcon [0] == 0) {
403+
return getImageDataUsingExtension(zoom);
404+
}
405+
Image image = Image.win32_new (null, SWT.ICON, hIcon [0], zoom);
425406
ImageData imageData = image.getImageData (zoom);
426407
image.dispose ();
427408
return imageData;
428409
}
429410

411+
private ImageData getImageDataUsingExtension(int zoom) {
412+
if (extension != null) {
413+
int initialNativeZoom = getPrimaryMonitorZoomAtStartup();
414+
SHFILEINFO shfi = new SHFILEINFO ();
415+
int flags = OS.SHGFI_ICON | OS.SHGFI_USEFILEATTRIBUTES;
416+
boolean useLargeIcon = 100 * zoom / initialNativeZoom >= 200;
417+
if(useLargeIcon) {
418+
flags |= OS.SHGFI_LARGEICON;
419+
initialNativeZoom *= 2;
420+
} else {
421+
flags |= OS.SHGFI_SMALLICON;
422+
}
423+
TCHAR pszPath = new TCHAR (0, extension, true);
424+
OS.SHGetFileInfo (pszPath.chars, OS.FILE_ATTRIBUTE_NORMAL, shfi, SHFILEINFO.sizeof, flags);
425+
if (shfi.hIcon != 0) {
426+
Image image = Image.win32_new (null, SWT.ICON, shfi.hIcon, initialNativeZoom);
427+
ImageData imageData = image.getImageData (zoom);
428+
image.dispose ();
429+
return imageData;
430+
}
431+
}
432+
return null;
433+
}
434+
430435
private int getPrimaryMonitorZoomAtStartup() {
431436
long hDC = OS.GetDC(0);
432437
int dpi = OS.GetDeviceCaps(hDC, OS.LOGPIXELSX);

0 commit comments

Comments
 (0)