Skip to content

Commit 80e0ccc

Browse files
committed
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 7c818d6 commit 80e0ccc

File tree

2 files changed

+47
-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

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

0 commit comments

Comments
 (0)