Skip to content

Commit 7825d59

Browse files
amartya4256HeikoKlare
authored andcommitted
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 20e1eaa commit 7825d59

File tree

6 files changed

+74
-28
lines changed

6 files changed

+74
-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
@@ -7534,6 +7534,28 @@ JNIEXPORT jint JNICALL OS_NATIVE(SHDRAGIMAGE_1sizeof)
75347534
}
75357535
#endif
75367536

7537+
#ifndef NO_SHDefExtractIcon
7538+
JNIEXPORT jint JNICALL OS_NATIVE(SHDefExtractIcon)
7539+
(JNIEnv *env, jclass that, jcharArray arg0, jint arg1, jint arg2, jlongArray arg3, jlongArray arg4, jint arg5)
7540+
{
7541+
jchar *lparg0=NULL;
7542+
jlong *lparg3=NULL;
7543+
jlong *lparg4=NULL;
7544+
jint rc = 0;
7545+
OS_NATIVE_ENTER(env, that, SHDefExtractIcon_FUNC);
7546+
if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
7547+
if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
7548+
if (arg4) if ((lparg4 = (*env)->GetLongArrayElements(env, arg4, NULL)) == NULL) goto fail;
7549+
rc = (jint)SHDefExtractIcon((LPWSTR)lparg0, arg1, arg2, (HICON FAR *)lparg3, (HICON FAR *)lparg4, arg5);
7550+
fail:
7551+
if (arg4 && lparg4) (*env)->ReleaseLongArrayElements(env, arg4, lparg4, 0);
7552+
if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
7553+
if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
7554+
OS_NATIVE_EXIT(env, that, SHDefExtractIcon_FUNC);
7555+
return rc;
7556+
}
7557+
#endif
7558+
75377559
#ifndef NO_SHELLEXECUTEINFO_1sizeof
75387560
JNIEXPORT jint JNICALL OS_NATIVE(SHELLEXECUTEINFO_1sizeof)
75397561
(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
@@ -569,6 +569,7 @@ typedef enum {
569569
SCROLLBARINFO_1sizeof_FUNC,
570570
SCROLLINFO_1sizeof_FUNC,
571571
SHDRAGIMAGE_1sizeof_FUNC,
572+
SHDefExtractIcon_FUNC,
572573
SHELLEXECUTEINFO_1sizeof_FUNC,
573574
SHFILEINFO_1sizeof_FUNC,
574575
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: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2302,6 +2302,11 @@ public static final boolean SetWindowText (long hWnd, TCHAR lpString) {
23022302
return SetWindowText (hWnd, lpString1);
23032303
}
23042304

2305+
public static final int SHDefExtractIcon (TCHAR lpszFile, int iIndex, int uFlags, long [] phiconLarge, long [] phiconSmall, int nIconSize) {
2306+
char [] lpszFile1 = lpszFile == null ? null : lpszFile.chars;
2307+
return SHDefExtractIcon (lpszFile1, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
2308+
}
2309+
23052310
public static final boolean UnregisterClass (TCHAR lpClassName, long hInstance) {
23062311
char [] lpClassName1 = lpClassName == null ? null : lpClassName.chars;
23072312
return UnregisterClass (lpClassName1, hInstance);
@@ -4455,6 +4460,12 @@ public static int HRESULT_FROM_WIN32(int x) {
44554460
* @param lpXform cast=(XFORM *),flags=no_out
44564461
*/
44574462
public static final native boolean SetWorldTransform(long hdc, float[] lpXform);
4463+
/**
4464+
* @param lpszFile cast=(LPWSTR)
4465+
* @param phiconLarge cast=(HICON FAR *)
4466+
* @param phiconSmall cast=(HICON FAR *)
4467+
*/
4468+
public static final native int SHDefExtractIcon (char [] lpszFile, int iIndex, int uFlags, long [] phiconLarge, long [] phiconSmall, int nIconSize);
44584469
/** @param pszPath cast=(LPCWSTR),flags=no_out */
44594470
public static final native long SHGetFileInfo (char [] pszPath, int dwFileAttributes, SHFILEINFO psfi, int cbFileInfo, int uFlags);
44604471
public static final native boolean ShellExecuteEx (SHELLEXECUTEINFO lpExecInfo);

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

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -379,28 +379,11 @@ 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-
}
382+
ImageData imageData = getImageDataUsingIconFilePath(zoom);
383+
return (imageData != null) ? imageData : getImageDataUsingExtension(zoom);
384+
}
385+
386+
private ImageData getImageDataUsingIconFilePath(int zoom) {
404387
int nIconIndex = 0;
405388
String fileName = iconName;
406389
int index = iconName.indexOf (',');
@@ -418,15 +401,44 @@ public ImageData getImageData (int zoom) {
418401
}
419402
}
420403
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);
404+
long [] hIcon = new long[1];
405+
int size = OS.GetSystemMetricsForDpi(OS.SM_CXSMICON, DPIUtil.mapZoomToDPI(zoom));
406+
OS.SHDefExtractIcon (lpszFile, nIconIndex, 0, hIcon, null, size);
407+
if (hIcon [0] == 0) {
408+
return null;
409+
}
410+
Image image = Image.win32_new (null, SWT.ICON, hIcon [0], zoom);
425411
ImageData imageData = image.getImageData (zoom);
426412
image.dispose ();
427413
return imageData;
428414
}
429415

416+
private ImageData getImageDataUsingExtension(int zoom) {
417+
if (extension != null) {
418+
// OS.SHGetFileInfo is System DPI-aware, hence it retrieves the icon with zoom
419+
// of primary monitor at the application startup
420+
int initialNativeZoom = getPrimaryMonitorZoomAtStartup();
421+
SHFILEINFO shfi = new SHFILEINFO ();
422+
int flags = OS.SHGFI_ICON | OS.SHGFI_USEFILEATTRIBUTES;
423+
boolean useLargeIcon = 100 * zoom / initialNativeZoom >= 200;
424+
if(useLargeIcon) {
425+
flags |= OS.SHGFI_LARGEICON;
426+
initialNativeZoom *= 2;
427+
} else {
428+
flags |= OS.SHGFI_SMALLICON;
429+
}
430+
TCHAR pszPath = new TCHAR (0, extension, true);
431+
OS.SHGetFileInfo (pszPath.chars, OS.FILE_ATTRIBUTE_NORMAL, shfi, SHFILEINFO.sizeof, flags);
432+
if (shfi.hIcon != 0) {
433+
Image image = Image.win32_new (null, SWT.ICON, shfi.hIcon, initialNativeZoom);
434+
ImageData imageData = image.getImageData (zoom);
435+
image.dispose ();
436+
return imageData;
437+
}
438+
}
439+
return null;
440+
}
441+
430442
private int getPrimaryMonitorZoomAtStartup() {
431443
long hDC = OS.GetDC(0);
432444
int dpi = OS.GetDeviceCaps(hDC, OS.LOGPIXELSX);

0 commit comments

Comments
 (0)