diff options
| author | Lakshmi Shanmugam | 2018-04-06 07:39:30 +0000 |
|---|---|---|
| committer | Lakshmi Shanmugam | 2018-04-10 17:05:51 +0000 |
| commit | 13e0a92eb06604985b73e89050f2814cadcbf876 (patch) | |
| tree | 4b5629b525dbec85c437ecf9e5d2b9cbb7384b06 | |
| parent | 1ef04fc233c30990e4fcfd616b06c8ff1ae9936c (diff) | |
| download | eclipse.platform.swt-13e0a92eb06604985b73e89050f2814cadcbf876.tar.gz eclipse.platform.swt-13e0a92eb06604985b73e89050f2814cadcbf876.tar.xz eclipse.platform.swt-13e0a92eb06604985b73e89050f2814cadcbf876.zip | |
Bug 480639: Provide monitor-specific DPI scaling / zoom level
Added API Monitor.getZoom() to get zoom on Mac & Windows
Change-Id: Ib1990d0cbb2190323f7204dd14c6674d99278efd
Signed-off-by: Lakshmi Shanmugam <lshanmug@in.ibm.com>
9 files changed, 214 insertions, 25 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os.c b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os.c index b1c54882a0..cdf5c9dac6 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os.c @@ -652,6 +652,23 @@ JNIEXPORT jint JNICALL OS_NATIVE(CRYPT_1OBJID_1BLOB_1sizeof) } #endif +#ifndef NO_Call +JNIEXPORT void JNICALL OS_NATIVE(Call) + (JNIEnv *env, jclass that, jintLong arg0, jintLong arg1, jint arg2, jintArray arg3, jintArray arg4) +{ + jint *lparg3=NULL; + jint *lparg4=NULL; + OS_NATIVE_ENTER(env, that, Call_FUNC); + if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail; + if (arg4) if ((lparg4 = (*env)->GetIntArrayElements(env, arg4, NULL)) == NULL) goto fail; + ((void (*)())arg0)(arg1, arg2, lparg3, lparg4); +fail: + if (arg4 && lparg4) (*env)->ReleaseIntArrayElements(env, arg4, lparg4, 0); + if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0); + OS_NATIVE_EXIT(env, that, Call_FUNC); +} +#endif + #ifndef NO_CallNextHookEx JNIEXPORT jintLong JNICALL OS_NATIVE(CallNextHookEx) (JNIEnv *env, jclass that, jintLong arg0, jint arg1, jintLong arg2, jintLong arg3) @@ -2850,6 +2867,18 @@ fail: } #endif +#ifndef NO_FreeLibrary +JNIEXPORT jboolean JNICALL OS_NATIVE(FreeLibrary) + (JNIEnv *env, jclass that, jintLong arg0) +{ + jboolean rc = 0; + OS_NATIVE_ENTER(env, that, FreeLibrary_FUNC); + rc = (jboolean)FreeLibrary((HMODULE)arg0); + OS_NATIVE_EXIT(env, that, FreeLibrary_FUNC); + return rc; +} +#endif + #ifndef NO_GCP_1RESULTS_1sizeof JNIEXPORT jint JNICALL OS_NATIVE(GCP_1RESULTS_1sizeof) (JNIEnv *env, jclass that) @@ -4524,6 +4553,22 @@ JNIEXPORT jint JNICALL OS_NATIVE(GetPolyFillMode) } #endif +#ifndef NO_GetProcAddress +JNIEXPORT jintLong JNICALL OS_NATIVE(GetProcAddress) + (JNIEnv *env, jclass that, jintLong arg0, jbyteArray arg1) +{ + jbyte *lparg1=NULL; + jintLong rc = 0; + OS_NATIVE_ENTER(env, that, GetProcAddress_FUNC); + if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail; + rc = (jintLong)GetProcAddress((HMODULE)arg0, (LPCTSTR)lparg1); +fail: + if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0); + OS_NATIVE_EXIT(env, that, GetProcAddress_FUNC); + return rc; +} +#endif + #ifndef NO_GetProcessHeap JNIEXPORT jintLong JNICALL OS_NATIVE(GetProcessHeap) (JNIEnv *env, jclass that) @@ -6720,6 +6765,38 @@ JNIEXPORT jintLong JNICALL OS_NATIVE(LoadImageW) } #endif +#ifndef NO_LoadLibraryA +JNIEXPORT jintLong JNICALL OS_NATIVE(LoadLibraryA) + (JNIEnv *env, jclass that, jbyteArray arg0) +{ + jbyte *lparg0=NULL; + jintLong rc = 0; + OS_NATIVE_ENTER(env, that, LoadLibraryA_FUNC); + if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail; + rc = (jintLong)LoadLibraryA((LPSTR)lparg0); +fail: + if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, 0); + OS_NATIVE_EXIT(env, that, LoadLibraryA_FUNC); + return rc; +} +#endif + +#ifndef NO_LoadLibraryW +JNIEXPORT jintLong JNICALL OS_NATIVE(LoadLibraryW) + (JNIEnv *env, jclass that, jcharArray arg0) +{ + jchar *lparg0=NULL; + jintLong rc = 0; + OS_NATIVE_ENTER(env, that, LoadLibraryW_FUNC); + if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail; + rc = (jintLong)LoadLibraryW((LPWSTR)lparg0); +fail: + if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0); + OS_NATIVE_EXIT(env, that, LoadLibraryW_FUNC); + return rc; +} +#endif + #ifndef NO_LocalFree JNIEXPORT jintLong JNICALL OS_NATIVE(LocalFree) (JNIEnv *env, jclass that, jintLong arg0) diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.c b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.c index 57b1770c28..535c93ce32 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.c @@ -59,6 +59,7 @@ char * OS_nativeFunctionNames[] = { "CRYPT_1BIT_1BLOB_1sizeof", "CRYPT_1INTEGER_1BLOB_1sizeof", "CRYPT_1OBJID_1BLOB_1sizeof", + "Call", "CallNextHookEx", "CallWindowProcA", "CallWindowProcW", @@ -217,6 +218,7 @@ char * OS_nativeFunctionNames[] = { "FillRect", "FormatMessageA", "FormatMessageW", + "FreeLibrary", "GCP_1RESULTS_1sizeof", "GESTURECONFIG_1sizeof", "GESTUREINFO_1sizeof", @@ -362,6 +364,7 @@ char * OS_nativeFunctionNames[] = { "GetParent", "GetPixel", "GetPolyFillMode", + "GetProcAddress", "GetProcessHeap", "GetProfileStringA", "GetProfileStringW", @@ -533,6 +536,8 @@ char * OS_nativeFunctionNames[] = { "LoadIconW", "LoadImageA", "LoadImageW", + "LoadLibraryA", + "LoadLibraryW", "LocalFree", "MAKELPARAM", "MAKELRESULT", diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.h index e2ba7db1a7..1e689e704a 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.h +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.h @@ -69,6 +69,7 @@ typedef enum { CRYPT_1BIT_1BLOB_1sizeof_FUNC, CRYPT_1INTEGER_1BLOB_1sizeof_FUNC, CRYPT_1OBJID_1BLOB_1sizeof_FUNC, + Call_FUNC, CallNextHookEx_FUNC, CallWindowProcA_FUNC, CallWindowProcW_FUNC, @@ -227,6 +228,7 @@ typedef enum { FillRect_FUNC, FormatMessageA_FUNC, FormatMessageW_FUNC, + FreeLibrary_FUNC, GCP_1RESULTS_1sizeof_FUNC, GESTURECONFIG_1sizeof_FUNC, GESTUREINFO_1sizeof_FUNC, @@ -372,6 +374,7 @@ typedef enum { GetParent_FUNC, GetPixel_FUNC, GetPolyFillMode_FUNC, + GetProcAddress_FUNC, GetProcessHeap_FUNC, GetProfileStringA_FUNC, GetProfileStringW_FUNC, @@ -543,6 +546,8 @@ typedef enum { LoadIconW_FUNC, LoadImageA_FUNC, LoadImageW_FUNC, + LoadLibraryA_FUNC, + LoadLibraryW_FUNC, LocalFree_FUNC, MAKELPARAM_FUNC, MAKELRESULT_FUNC, diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java index 0f6fd03e7b..620a81f219 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java @@ -958,6 +958,7 @@ public class OS extends C { public static final int MCN_SELECT = MCN_FIRST + 4; public static final int MCS_NOTODAY = 0x0010; public static final int MDIS_ALLCHILDSTYLES = 0x0001; + public static final int MDT_EFFECTIVE_DPI = 0; public static final int MFS_CHECKED = 0x8; public static final int MFS_DISABLED = 0x3; public static final int MFS_GRAYED = 0x3; @@ -2166,6 +2167,26 @@ public static final native int WINDOWPLACEMENT_sizeof (); public static final native int WINDOWPOS_sizeof (); public static final native int WNDCLASS_sizeof (); +public static final int GetDpiForMonitor (long /*int*/ hmonitor, int dpiType, int [] dpiX, int [] dpiY) { + TCHAR lpLibFileName = new TCHAR (0, "Shcore.dll", true); //$NON-NLS-1$ + long /*int*/ hModule = OS.LoadLibrary (lpLibFileName); + if (hModule != 0) { + String name = "GetDpiForMonitor\0"; //$NON-NLS-1$ + byte [] lpProcName = new byte [name.length ()]; + for (int i=0; i<lpProcName.length; i++) { + lpProcName [i] = (byte) name.charAt (i); + } + long /*int*/ DllGetDpiForMonitor = OS.GetProcAddress (hModule, lpProcName); + if (DllGetDpiForMonitor != 0) { + dpiX [0] = dpiY [0] = -1; + OS.Call (DllGetDpiForMonitor, hmonitor, dpiType, dpiX, dpiY); + } + OS.FreeLibrary (hModule); + return dpiX [0] == -1 ? -1 : 0; // return result if API call succeeded + } + return -1; +} + /** Ansi/Unicode wrappers */ public static final long /*int*/ AddFontResourceEx (TCHAR lpszFilename, int fl, long /*int*/ pdv) { @@ -2679,6 +2700,15 @@ public static final long /*int*/ LoadImage (long /*int*/ hinst, long /*int*/ lps return LoadImageA (hinst, lpszName, uType, cxDesired, cyDesired, fuLoad); } +public static final long /*int*/ LoadLibrary (TCHAR lpLibFileName) { + if (IsUnicode) { + char [] lpLibFileName1 = lpLibFileName == null ? null : lpLibFileName.chars; + return LoadLibraryW (lpLibFileName1); + } + byte [] lpLibFileName1 = lpLibFileName == null ? null : lpLibFileName.bytes; + return LoadLibraryA (lpLibFileName1); +} + public static final int MapVirtualKey (int uCode, int uMapType) { if (IsUnicode) return MapVirtualKeyW (uCode, uMapType); return MapVirtualKeyA (uCode, uMapType); @@ -3253,6 +3283,7 @@ public static final native boolean BringWindowToTop (long /*int*/ hWnd); public static final native int BufferedPaintInit (); /** @method flags=dynamic */ public static final native int BufferedPaintUnInit (); +public static native void Call (long /*int*/ address, long /*int*/ hmonitor, int dpiType, int[] dpiX, int[] dpiY); /** * @param hhk cast=(HHOOK) * @param wParam cast=(WPARAM) @@ -3743,6 +3774,8 @@ public static final native int FormatMessageA (int dwFlags, long /*int*/ lpSourc * @param Arguments cast=(va_list*) */ public static final native int FormatMessageW (int dwFlags, long /*int*/ lpSource, int dwMessageId, int dwLanguageId, long /*int*/ [] lpBuffer, int nSize, long /*int*/ Arguments); +/** @param hLibModule cast=(HMODULE) */ +public static final native boolean FreeLibrary (long /*int*/ hLibModule); /** @param dwLimit cast=(DWORD) */ public static final native int GdiSetBatchLimit (int dwLimit); public static final native int GET_WHEEL_DELTA_WPARAM(long /*int*/ wParam); @@ -4054,6 +4087,11 @@ public static final native boolean OpenPrinterW (char[] pPrinterName, long /*int * @param pDefault cast=(LPPRINTER_DEFAULTS) */ public static final native boolean OpenPrinterA (byte[] pPrinterName, long /*int*/ [] phPrinter, long /*int*/ pDefault); +/** + * @param hModule cast=(HMODULE) + * @param lpProcName cast=(LPCTSTR) + */ +public static final native long /*int*/ GetProcAddress (long /*int*/ hModule, byte [] lpProcName); public static final native long /*int*/ GetProcessHeap (); /** * @param lpAppName cast=(LPWSTR) @@ -4494,6 +4532,10 @@ public static final native long /*int*/ LoadImageW (long /*int*/ hinst, long /*i * @param lpszName cast=(LPSTR) */ public static final native long /*int*/ LoadImageA (long /*int*/ hinst, long /*int*/ lpszName, int uType, int cxDesired, int cyDesired, int fuLoad); +/** @param lpLibFileName cast=(LPWSTR) */ +public static final native long /*int*/ LoadLibraryW (char [] lpLibFileName); +/** @param lpLibFileName cast=(LPSTR) */ +public static final native long /*int*/ LoadLibraryA (byte [] lpLibFileName); /** @param hMem cast=(HLOCAL) */ public static final native long /*int*/ LocalFree (long /*int*/ hMem); public static final native int LODWORD (long l); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java index db5b77ba3f..021e5b7988 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java @@ -1693,6 +1693,7 @@ public Monitor [] getMonitors () { monitor.clientY = (int)(primaryFrame.height - (visibleFrame.y + visibleFrame.height)); monitor.clientWidth = (int)visibleFrame.width; monitor.clientHeight = (int)visibleFrame.height; + monitor.zoom = (int) (screen.backingScaleFactor() * 100); monitors [i] = monitor; } return monitors; @@ -1726,6 +1727,7 @@ public Monitor getPrimaryMonitor () { monitor.clientY = (int)(frame.height - (visibleFrame.y + visibleFrame.height)); monitor.clientWidth = (int)visibleFrame.width; monitor.clientHeight = (int)visibleFrame.height; + monitor.zoom = (int) (screen.backingScaleFactor() * 100); return monitor; } @@ -6542,3 +6544,9 @@ static long /*int*/ windowProc(long /*int*/ id, long /*int*/ sel, long /*int*/ a } } + +class MonitorUtil { + static int getZoom (Monitor monitor) { + return monitor.zoom; + } +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java index 17708de993..1ef8de15be 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java @@ -39,6 +39,8 @@ public class DPIUtil { private static AutoScaleMethod autoScaleMethodSetting = AutoScaleMethod.AUTO; private static AutoScaleMethod autoScaleMethod = AutoScaleMethod.NEAREST; + private static String autoScaleValue; + /** * System property that controls the autoScale functionality. * <ul> @@ -73,6 +75,8 @@ public class DPIUtil { */ private static final String SWT_AUTOSCALE_METHOD = "swt.autoScale.method"; static { + autoScaleValue = System.getProperty (SWT_AUTOSCALE); + String value = System.getProperty (SWT_AUTOSCALE_METHOD); if (value != null) { if (AutoScaleMethod.NEAREST.name().equalsIgnoreCase(value)) { @@ -419,31 +423,7 @@ public static int getDeviceZoom() { public static void setDeviceZoom (int nativeDeviceZoom) { DPIUtil.nativeDeviceZoom = nativeDeviceZoom; - int deviceZoom = 0; - String value = System.getProperty (SWT_AUTOSCALE); - if (value != null) { - if ("false".equalsIgnoreCase (value)) { - deviceZoom = 100; - } else if ("quarter".equalsIgnoreCase (value)) { - deviceZoom = (int) (Math.round (nativeDeviceZoom / 25f) * 25); - } else if ("exact".equalsIgnoreCase (value)) { - deviceZoom = nativeDeviceZoom; - } else { - try { - int zoom = Integer.parseInt (value); - deviceZoom = Math.max (Math.min (zoom, 1600), 25); - } catch (NumberFormatException e) { - // unsupported value, use default - } - } - } - if (deviceZoom == 0) { // || "integer".equalsIgnoreCase (value) || "integer200".equalsIgnoreCase (value) - deviceZoom = Math.max ((nativeDeviceZoom + 25) / 100 * 100, 100); - if (!"integer".equalsIgnoreCase(value)) { - // integer200, or default - deviceZoom = Math.min (deviceZoom, 200); - } - } + int deviceZoom = getZoomForAutoscaleProperty (nativeDeviceZoom); DPIUtil.deviceZoom = deviceZoom; System.setProperty("org.eclipse.swt.internal.deviceZoom", Integer.toString(deviceZoom)); @@ -456,6 +436,34 @@ public static void setDeviceZoom (int nativeDeviceZoom) { } } +public static int getZoomForAutoscaleProperty (int nativeDeviceZoom) { + int zoom = 0; + if (autoScaleValue != null) { + if ("false".equalsIgnoreCase (autoScaleValue)) { + zoom = 100; + } else if ("quarter".equalsIgnoreCase (autoScaleValue)) { + zoom = (int) (Math.round (nativeDeviceZoom / 25f) * 25); + } else if ("exact".equalsIgnoreCase (autoScaleValue)) { + zoom = nativeDeviceZoom; + } else { + try { + int zoomValue = Integer.parseInt (autoScaleValue); + zoom = Math.max (Math.min (zoomValue, 1600), 25); + } catch (NumberFormatException e) { + // unsupported value, use default + } + } + } + if (zoom == 0) { // || "integer".equalsIgnoreCase (value) || "integer200".equalsIgnoreCase (value) + zoom = Math.max ((nativeDeviceZoom + 25) / 100 * 100, 100); + if (!"integer".equalsIgnoreCase(autoScaleValue)) { + // integer200, or default + zoom = Math.min (zoom, 200); + } + } + return zoom; +} + /** * AutoScale ImageDataProvider. */ diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Monitor.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Monitor.java index b797fd8193..6120916807 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Monitor.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Monitor.java @@ -25,6 +25,7 @@ public final class Monitor { long /*int*/ handle; int x, y, width, height; int clientX, clientY, clientWidth, clientHeight; + int zoom; /** * Prevents uninitialized instances from being created outside the package. @@ -71,6 +72,17 @@ public Rectangle getClientArea () { return new Rectangle (clientX, clientY, clientWidth, clientHeight); } +/** + * Returns the zoom value for the monitor + * + * @return monitor's zoom value + * + * @since 3.107 + */ +public int getZoom () { + return MonitorUtil.getZoom (this); +} + void setBounds (Rectangle rect) { x = rect.x; y = rect.y; @@ -85,6 +97,10 @@ void setClientArea (Rectangle rect) { clientHeight = rect.height; } +void setZoom (int zoom) { + this.zoom = zoom; +} + /** * Returns an integer hash code for the receiver. Any two * objects that return <code>true</code> when passed to @@ -94,6 +110,7 @@ void setClientArea (Rectangle rect) { * @return the receiver's hash * * @see #equals(Object) + * */ @Override public int hashCode () { diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java index d17b7e5579..e00c1e60cf 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java @@ -5957,3 +5957,9 @@ protected long /*int*/ gsettingsProc (long /*int*/ gobject, long /*int*/ arg1, l } + +class MonitorUtil { + static int getZoom (Monitor monitor) { + return monitor.zoom; + } +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java index fc7698f4fa..e0aa444757 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java @@ -4990,3 +4990,24 @@ static char [] withCrLf (char [] string) { } } + +class MonitorUtil { + static int getZoom (Monitor monitor) { + if (OS.WIN32_VERSION >= OS.VERSION (6, 3)) { + int[] dpiX = new int[1]; + int[] dpiY = new int[1]; + int result = OS.GetDpiForMonitor (monitor.handle, OS.MDT_EFFECTIVE_DPI, dpiX, dpiY); + result = (result == OS.S_OK) ? DPIUtil.mapDPIToZoom (dpiX[0]) : 100; + return DPIUtil.getZoomForAutoscaleProperty (result); + } + int dpi = getSystemDPI (); + return DPIUtil.mapDPIToZoom (dpi); + } + + static int getSystemDPI () { + long /*int*/ hDC = OS.GetDC (0); + int dpi = OS.GetDeviceCaps (hDC, OS.LOGPIXELSX); + OS.ReleaseDC (0, hDC); + return dpi; + } +} |
