Skip to content

Commit 4325d7b

Browse files
amartya4256HeikoKlare
authored andcommitted
MenuItem Image Scaling with DPI aware metrics #62
This commit contributes to scaling of the MenuItem::hBitmap with the DPI -aware System Metrics for the size of the SM_CYMENUCHECK or the size obtained by menuItem zoom. It also corrects the zoom in specific cases where the images are not consistently drawn on the context menu. Contributes to #62 and #127
1 parent 22e8829 commit 4325d7b

File tree

2 files changed

+48
-2
lines changed
  • bundles/org.eclipse.swt
    • Eclipse SWT PI/win32/org/eclipse/swt/internal/win32
    • Eclipse SWT/win32/org/eclipse/swt/widgets

2 files changed

+48
-2
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,7 @@ public class OS extends C {
12481248
public static final int SM_CYFOCUSBORDER = 84;
12491249
public static final int SM_CYHSCROLL = 0x3;
12501250
public static final int SM_CYMENU = 0xf;
1251+
public static final int SM_CYMENUCHECK = 72;
12511252
public static final int SM_CXMINTRACK = 34;
12521253
public static final int SM_CYMINTRACK = 35;
12531254
public static final int SM_CXMAXTRACK = 59;

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/MenuItem.java

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -781,8 +781,7 @@ public void setImage (Image image) {
781781
info.hbmpItem = OS.HBMMENU_CALLBACK;
782782
} else {
783783
if (OS.IsAppThemed ()) {
784-
if (hBitmap != 0) OS.DeleteObject (hBitmap);
785-
info.hbmpItem = hBitmap = image != null ? Display.create32bitDIB (image, getZoom()) : 0;
784+
info.hbmpItem = hBitmap = getMenuItemIconBitmapHandle(image);
786785
} else {
787786
info.hbmpItem = image != null ? OS.HBMMENU_CALLBACK : 0;
788787
}
@@ -792,6 +791,52 @@ public void setImage (Image image) {
792791
parent.redraw ();
793792
}
794793

794+
private long getMenuItemIconBitmapHandle(Image image) {
795+
if (image == null) {
796+
return 0;
797+
}
798+
if (hBitmap != 0) OS.DeleteObject (hBitmap);
799+
int zoom = adaptZoomForMenuItem(getZoom());
800+
return Display.create32bitDIB (image, zoom);
801+
}
802+
803+
private int adaptZoomForMenuItem(int currentZoom) {
804+
int primaryMonitorZoomAtAppStartUp = getPrimaryMonitorZoomAtStartup();
805+
/*
806+
* Windows has inconsistent behavior when setting the size of MenuItem image and
807+
* hence we need to adjust the size of the images as per different kind of zoom
808+
* level, i.e. full (100s), half (50s) and quarter (25s). The image size per
809+
* zoom level is also affected by the primaryMonitorZoomAtAppStartUp. The
810+
* implementation below is based on the pattern observed for all the zoom values
811+
* and what fits the best for these zoom level types.
812+
*/
813+
if (primaryMonitorZoomAtAppStartUp > currentZoom && isQuarterZoom(currentZoom)) {
814+
return currentZoom - 25;
815+
}
816+
if (!isHalfZoom(primaryMonitorZoomAtAppStartUp) && isHalfZoom(currentZoom)) {
817+
// Use the size recommended by System Metrics. This value only holds
818+
// for this case and does not work consistently for other cases.
819+
double expectedSize = getSystemMetrics(OS.SM_CYMENUCHECK);
820+
return (int) ((expectedSize / image.getBounds().height) * 100);
821+
}
822+
return currentZoom;
823+
}
824+
825+
private static boolean isHalfZoom(int zoom) {
826+
return zoom % 50 == 0 && zoom % 100 != 0;
827+
}
828+
829+
private static boolean isQuarterZoom(int zoom) {
830+
return zoom % 10 != 0 && zoom % 25 == 0;
831+
}
832+
833+
private static int getPrimaryMonitorZoomAtStartup() {
834+
long hDC = OS.GetDC(0);
835+
int dpi = OS.GetDeviceCaps(hDC, OS.LOGPIXELSX);
836+
OS.ReleaseDC(0, hDC);
837+
return DPIUtil.mapDPIToZoom(dpi);
838+
}
839+
795840
/**
796841
* Sets the receiver's pull down menu to the argument.
797842
* Only <code>CASCADE</code> menu items can have a

0 commit comments

Comments
 (0)