From 3ff98ad73b3645f7ff5a19974762857edac1f386 Mon Sep 17 00:00:00 2001 From: xbpiao Date: Thu, 22 Jan 2026 23:06:13 +0800 Subject: [PATCH 1/8] Fixes high DPI compatibility on Windows platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 参考:https://learn.microsoft.com/zh-cn/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows --- .../cocos/platform/win32/modules/Screen.cpp | 20 +++++++++++++------ .../platform/win32/modules/SystemWindow.cpp | 16 +++++++++------ .../frameworks/runtime-src/CMakeLists.txt | 4 ++++ pal/input/native/mouse-input.ts | 10 ++++++++-- templates/windows/CMakeLists.txt | 1 + 5 files changed, 37 insertions(+), 14 deletions(-) diff --git a/native/cocos/platform/win32/modules/Screen.cpp b/native/cocos/platform/win32/modules/Screen.cpp index a86c9cfecf6..8d758be685c 100644 --- a/native/cocos/platform/win32/modules/Screen.cpp +++ b/native/cocos/platform/win32/modules/Screen.cpp @@ -31,19 +31,27 @@ namespace cc { int Screen::getDPI() const { + // 参考:https://learn.microsoft.com/zh-cn/windows/win32/api/wingdi/nf-wingdi-getdevicecaps static int dpi = -1; if (dpi == -1) { + + dpi = 96; HDC hScreenDC = GetDC(nullptr); - int PixelsX = GetDeviceCaps(hScreenDC, HORZRES); - int MMX = GetDeviceCaps(hScreenDC, HORZSIZE); - ReleaseDC(nullptr, hScreenDC); - dpi = static_cast(254.0f * PixelsX / MMX / 10); + if (hScreenDC) { + // LOGPIXELSX 对应水平方向每逻辑英寸的像素点数 + dpi = GetDeviceCaps(hScreenDC, LOGPIXELSX); + ReleaseDC(nullptr, hScreenDC); + } + // win10 1607 以上 + // HWND hDesktop = GetDesktopWindow(); + // dpi = GetDpiForWindow(hDesktop); } return dpi; } float Screen::getDevicePixelRatio() const { - return 1; + // return 1; + return Screen::getDPI() / 96.0f; } void Screen::setKeepScreenOn(bool value) { @@ -73,4 +81,4 @@ void Screen::setDisplayStats(bool isShow) { se::ScriptEngine::getInstance()->evalString(commandBuf); } -} // namespace cc \ No newline at end of file +} // namespace cc diff --git a/native/cocos/platform/win32/modules/SystemWindow.cpp b/native/cocos/platform/win32/modules/SystemWindow.cpp index 1d58d8c081f..29f21204dfa 100644 --- a/native/cocos/platform/win32/modules/SystemWindow.cpp +++ b/native/cocos/platform/win32/modules/SystemWindow.cpp @@ -29,6 +29,7 @@ #include "engine/EngineEvents.h" #include "platform/SDLHelper.h" #include "platform/win32/WindowsPlatform.h" +#include "platform/interfaces/modules/IScreen.h" namespace cc { SystemWindow::SystemWindow(uint32_t windowId, void *externalHandle) @@ -45,13 +46,14 @@ SystemWindow::~SystemWindow() { bool SystemWindow::createWindow(const char *title, int w, int h, int flags) { - _window = SDLHelper::createWindow(title, w, h, flags); + float dpr = cc::BasePlatform::getPlatform()->getInterface()->getDevicePixelRatio(); + _width = w * dpr; + _height = h * dpr; + _window = SDLHelper::createWindow(title, _width, _height, flags); if (!_window) { return false; } - _width = w; - _height = h; _windowHandle = SDLHelper::getWindowHandle(_window); return true; } @@ -59,13 +61,15 @@ bool SystemWindow::createWindow(const char *title, bool SystemWindow::createWindow(const char *title, int x, int y, int w, int h, int flags) { - _window = SDLHelper::createWindow(title, x, y, w, h, flags); + float dpr = cc::BasePlatform::getPlatform()->getInterface()->getDevicePixelRatio(); + _width = w * dpr; + _height = h * dpr; + + _window = SDLHelper::createWindow(title, x, y, _width, _height, flags); if (!_window) { return false; } - _width = w; - _height = h; _windowHandle = SDLHelper::getWindowHandle(_window); return true; diff --git a/native/tools/simulator/frameworks/runtime-src/CMakeLists.txt b/native/tools/simulator/frameworks/runtime-src/CMakeLists.txt index e05aa92c7ef..949a20a674e 100644 --- a/native/tools/simulator/frameworks/runtime-src/CMakeLists.txt +++ b/native/tools/simulator/frameworks/runtime-src/CMakeLists.txt @@ -152,6 +152,10 @@ else() add_executable(${LIB_NAME} ${PROJ_SOURCES} ${PROJ_EXTRA_SOURCE}) endif() +if(WINDOWS AND MSVC) + set_property(TARGET ${LIB_NAME} PROPERTY VS_DPI_AWARE "PerMonitor") +endif() + target_link_libraries(${LIB_NAME} ${ENGINE_NAME} simulator) target_include_directories(${LIB_NAME} PRIVATE Classes diff --git a/pal/input/native/mouse-input.ts b/pal/input/native/mouse-input.ts index 45e2bfde9c3..97da67f0b52 100644 --- a/pal/input/native/mouse-input.ts +++ b/pal/input/native/mouse-input.ts @@ -116,7 +116,10 @@ export class MouseInputSource { private _getLocation (event: jsb.MouseEvent): Vec2 { const window = this._windowManager.getWindow(event.windowId); const windowSize = window.getViewSize(); - const dpr = screenAdapter.devicePixelRatio; + let dpr = screenAdapter.devicePixelRatio; + if (systemInfo.os === OS.WINDOWS) { // 在windows下DPI变化时下发的是实际坐标 + dpr = 1; + } const x = event.x * dpr; const y = windowSize.height - event.y * dpr; return new Vec2(x, y); @@ -187,7 +190,10 @@ export class MouseInputSource { const eventMouse = new EventMouse(eventType, false, this._preMousePos, mouseEvent.windowId); eventMouse.setLocation(location.x, location.y); eventMouse.setButton(button); - const dpr = screenAdapter.devicePixelRatio; + let dpr = screenAdapter.devicePixelRatio; + if (systemInfo.os === OS.WINDOWS) { // 在windows下DPI变化时下发的是实际坐标 + dpr = 1; + } eventMouse.movementX = typeof mouseEvent.xDelta === 'undefined' ? 0 : mouseEvent.xDelta * dpr; eventMouse.movementY = typeof mouseEvent.yDelta === 'undefined' ? 0 : mouseEvent.yDelta * dpr; // update previous mouse position. diff --git a/templates/windows/CMakeLists.txt b/templates/windows/CMakeLists.txt index 9f3d15f91f8..e000ac49c70 100644 --- a/templates/windows/CMakeLists.txt +++ b/templates/windows/CMakeLists.txt @@ -14,4 +14,5 @@ cc_windows_before_target(${EXECUTABLE_NAME}) add_executable(${EXECUTABLE_NAME} ${CC_ALL_SOURCES} ) +set_property(TARGET ${EXECUTABLE_NAME} PROPERTY VS_DPI_AWARE "PerMonitor") cc_windows_after_target(${EXECUTABLE_NAME}) \ No newline at end of file From 27daae8f35c89cdff21a286d831fa87ff76d9538 Mon Sep 17 00:00:00 2001 From: xbpiao Date: Fri, 23 Jan 2026 05:47:03 +0800 Subject: [PATCH 2/8] update mouse-inputs.ts fix Trailing spaces --- pal/input/native/mouse-input.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pal/input/native/mouse-input.ts b/pal/input/native/mouse-input.ts index 97da67f0b52..eb7c47012ad 100644 --- a/pal/input/native/mouse-input.ts +++ b/pal/input/native/mouse-input.ts @@ -119,7 +119,7 @@ export class MouseInputSource { let dpr = screenAdapter.devicePixelRatio; if (systemInfo.os === OS.WINDOWS) { // 在windows下DPI变化时下发的是实际坐标 dpr = 1; - } + } const x = event.x * dpr; const y = windowSize.height - event.y * dpr; return new Vec2(x, y); From b5dac294f2669db114f2d93bff504540ab2d31ec Mon Sep 17 00:00:00 2001 From: xbpiao Date: Fri, 23 Jan 2026 06:01:54 +0800 Subject: [PATCH 3/8] update native\cocos\platform\win32\modules\Screen.cpp Delete unnecessary comments --- native/cocos/platform/win32/modules/Screen.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/native/cocos/platform/win32/modules/Screen.cpp b/native/cocos/platform/win32/modules/Screen.cpp index 8d758be685c..e1ab5267ae9 100644 --- a/native/cocos/platform/win32/modules/Screen.cpp +++ b/native/cocos/platform/win32/modules/Screen.cpp @@ -50,8 +50,7 @@ int Screen::getDPI() const { } float Screen::getDevicePixelRatio() const { - // return 1; - return Screen::getDPI() / 96.0f; + return getDPI() / 96.0f; } void Screen::setKeepScreenOn(bool value) { From 31a930a56d7ed83fb400b521857e5cb5d3de6863 Mon Sep 17 00:00:00 2001 From: xbpiao Date: Fri, 23 Jan 2026 08:44:17 +0800 Subject: [PATCH 4/8] update compatibility-info.json >=3.8.0 --- templates/compatibility-info.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compatibility-info.json b/templates/compatibility-info.json index f6ce2ecba26..bd654311896 100644 --- a/templates/compatibility-info.json +++ b/templates/compatibility-info.json @@ -1,5 +1,5 @@ { "native": { - "default": ">=3.6.0" + "default": ">=3.8.0" } } \ No newline at end of file From 59ef482c3aaefe2f7cdcc703376d79bf61c71ac7 Mon Sep 17 00:00:00 2001 From: xbpiao Date: Sat, 24 Jan 2026 11:29:48 +0800 Subject: [PATCH 5/8] Fixes Touch coordinates on the native Windows platform --- native/cocos/platform/SDLHelper.cpp | 3 +++ pal/input/native/touch-input.ts | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/native/cocos/platform/SDLHelper.cpp b/native/cocos/platform/SDLHelper.cpp index 84b762f6b22..81795ed174e 100644 --- a/native/cocos/platform/SDLHelper.cpp +++ b/native/cocos/platform/SDLHelper.cpp @@ -315,6 +315,7 @@ void SDLHelper::dispatchSDLEvent(uint32_t windowId, const SDL_Event &sdlEvent) { const SDL_TouchFingerEvent &event = sdlEvent.tfinger; touch.type = TouchEvent::Type::ENDED; touch.touches = {TouchInfo(event.x, event.y, (int)event.fingerId)}; + touch.windowId = event.windowID; events::Touch::broadcast(touch); break; } @@ -322,6 +323,7 @@ void SDLHelper::dispatchSDLEvent(uint32_t windowId, const SDL_Event &sdlEvent) { const SDL_TouchFingerEvent &event = sdlEvent.tfinger; touch.type = TouchEvent::Type::BEGAN; touch.touches = {TouchInfo(event.x, event.y, (int)event.fingerId)}; + touch.windowId = event.windowID; events::Touch::broadcast(touch); break; } @@ -329,6 +331,7 @@ void SDLHelper::dispatchSDLEvent(uint32_t windowId, const SDL_Event &sdlEvent) { const SDL_TouchFingerEvent &event = sdlEvent.tfinger; touch.type = TouchEvent::Type::MOVED; touch.touches = {TouchInfo(event.x, event.y, (int)event.fingerId)}; + touch.windowId = event.windowID; events::Touch::broadcast(touch); break; } diff --git a/pal/input/native/touch-input.ts b/pal/input/native/touch-input.ts index 8a2a751f6bb..13ee0726665 100644 --- a/pal/input/native/touch-input.ts +++ b/pal/input/native/touch-input.ts @@ -28,6 +28,8 @@ import { EventTarget } from '../../../cocos/core/event'; import { EventTouch, Touch as CCTouch } from '../../../cocos/input/types'; import { touchManager } from '../touch-manager'; import { InputEventType } from '../../../cocos/input/types/event-enum'; +import { systemInfo } from 'pal/system-info'; +import { OS } from '../../system-info/enum-type'; export type TouchCallback = (res: EventTouch) => void; @@ -114,7 +116,12 @@ export class TouchInputSource { private _dispatchEvent (eventType: InputEventType, changedTouches: Touch[], windowId: number): void { const handleTouches: CCTouch[] = []; const length = changedTouches.length; - const windowSize = this._windowManager.getWindow(windowId).getViewSize() as Size; + const window = this._windowManager.getWindow(windowId); + if (window === null) { + return; + } + const windowSize = window.getViewSize(); + // const windowSize = this._windowManager.getWindow(windowId).getViewSize() as Size; for (let i = 0; i < length; ++i) { const changedTouch = changedTouches[i]; const touchID = changedTouch.identifier; @@ -144,7 +151,10 @@ export class TouchInputSource { } private _getLocation (touch: globalThis.Touch, windowSize: Size): Vec2 { - const dpr = screenAdapter.devicePixelRatio; + let dpr = screenAdapter.devicePixelRatio; + if (systemInfo.os === OS.WINDOWS) { // 在windows下DPI变化时下发的是实际坐标 + dpr = 1; + } const x = touch.clientX * dpr; const y = windowSize.height - touch.clientY * dpr; return new Vec2(x, y); From 799098009ab8643aacb5b103bb4307140df282be Mon Sep 17 00:00:00 2001 From: xbpiao Date: Sat, 24 Jan 2026 11:50:55 +0800 Subject: [PATCH 6/8] update touch-input.ts fix Trailing spaces --- pal/input/native/touch-input.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pal/input/native/touch-input.ts b/pal/input/native/touch-input.ts index 13ee0726665..eba0817538b 100644 --- a/pal/input/native/touch-input.ts +++ b/pal/input/native/touch-input.ts @@ -154,7 +154,7 @@ export class TouchInputSource { let dpr = screenAdapter.devicePixelRatio; if (systemInfo.os === OS.WINDOWS) { // 在windows下DPI变化时下发的是实际坐标 dpr = 1; - } + } const x = touch.clientX * dpr; const y = windowSize.height - touch.clientY * dpr; return new Vec2(x, y); From cb0b313ebfb461779bf106650d892f25bb79db7e Mon Sep 17 00:00:00 2001 From: xbpiao Date: Sat, 24 Jan 2026 12:12:47 +0800 Subject: [PATCH 7/8] update touch-input.ts fix Trailing spaces --- pal/input/native/touch-input.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pal/input/native/touch-input.ts b/pal/input/native/touch-input.ts index eba0817538b..af25b42279f 100644 --- a/pal/input/native/touch-input.ts +++ b/pal/input/native/touch-input.ts @@ -23,12 +23,12 @@ */ import { screenAdapter } from 'pal/screen-adapter'; +import { systemInfo } from 'pal/system-info'; import { Size, Vec2 } from '../../../cocos/core/math'; import { EventTarget } from '../../../cocos/core/event'; import { EventTouch, Touch as CCTouch } from '../../../cocos/input/types'; import { touchManager } from '../touch-manager'; import { InputEventType } from '../../../cocos/input/types/event-enum'; -import { systemInfo } from 'pal/system-info'; import { OS } from '../../system-info/enum-type'; export type TouchCallback = (res: EventTouch) => void; @@ -120,8 +120,7 @@ export class TouchInputSource { if (window === null) { return; } - const windowSize = window.getViewSize(); - // const windowSize = this._windowManager.getWindow(windowId).getViewSize() as Size; + const windowSize = window.getViewSize() as Size; for (let i = 0; i < length; ++i) { const changedTouch = changedTouches[i]; const touchID = changedTouch.identifier; From c3f7f8f7539cdc7afba0e1e1993c970d45069b92 Mon Sep 17 00:00:00 2001 From: xbpiao Date: Sat, 24 Jan 2026 21:10:20 +0800 Subject: [PATCH 8/8] Fix Editbox-win32 to adapt to High DPI --- native/cocos/application/BaseGame.cpp | 3 ++- native/cocos/platform/SDLHelper.cpp | 19 ++++++++++++++++--- native/cocos/ui/edit-box/EditBox-win32.cpp | 14 ++++++++------ 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/native/cocos/application/BaseGame.cpp b/native/cocos/application/BaseGame.cpp index 73b774e7f4c..1462e46fcb3 100644 --- a/native/cocos/application/BaseGame.cpp +++ b/native/cocos/application/BaseGame.cpp @@ -58,7 +58,8 @@ int BaseGame::init() { _windowInfo.height = _windowInfo.height == -1 ? 600 : _windowInfo.height; _windowInfo.flags = _windowInfo.flags == -1 ? cc::ISystemWindow::CC_WINDOW_SHOWN | cc::ISystemWindow::CC_WINDOW_RESIZABLE | - cc::ISystemWindow::CC_WINDOW_INPUT_FOCUS + cc::ISystemWindow::CC_WINDOW_INPUT_FOCUS | + cc::ISystemWindow::CC_WINDOW_ALLOW_HIGHDPI : _windowInfo.flags; std::call_once(_windowCreateFlag, [&]() { ISystemWindowInfo info; diff --git a/native/cocos/platform/SDLHelper.cpp b/native/cocos/platform/SDLHelper.cpp index 81795ed174e..815fbd4588a 100644 --- a/native/cocos/platform/SDLHelper.cpp +++ b/native/cocos/platform/SDLHelper.cpp @@ -155,6 +155,9 @@ SDLHelper::~SDLHelper() { } int SDLHelper::init() { +#if CC_PLATFORM == CC_PLATFORM_WINDOWS + SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0"); +#endif if (SDL_Init(SDL_INIT_VIDEO) < 0) { // Display error message CC_LOG_ERROR("SDL could not initialize! SDL_Error: %s\n", SDL_GetError()); @@ -195,20 +198,30 @@ void SDLHelper::dispatchWindowEvent(uint32_t windowId, const SDL_WindowEvent &we break; } case SDL_WINDOWEVENT_SIZE_CHANGED: { - auto *screen = BasePlatform::getPlatform()->getInterface(); - CC_ASSERT(screen != nullptr); ev.type = WindowEvent::Type::SIZE_CHANGED; +#if CC_PLATFORM == CC_PLATFORM_WINDOWS + ev.width = wevent.data1; + ev.height = wevent.data2; +#else + auto *screen = BasePlatform::getPlatform()->getInterface(); + CC_ASSERT(screen != nullptr); ev.width = wevent.data1 * screen->getDevicePixelRatio(); ev.height = wevent.data2 * screen->getDevicePixelRatio(); +#endif events::WindowEvent::broadcast(ev); break; } case SDL_WINDOWEVENT_RESIZED: { + ev.type = WindowEvent::Type::RESIZED; +#if CC_PLATFORM == CC_PLATFORM_WINDOWS + ev.width = wevent.data1; + ev.height = wevent.data2; +#else auto *screen = BasePlatform::getPlatform()->getInterface(); CC_ASSERT(screen != nullptr); - ev.type = WindowEvent::Type::RESIZED; ev.width = wevent.data1 * screen->getDevicePixelRatio(); ev.height = wevent.data2 * screen->getDevicePixelRatio(); +#endif events::WindowEvent::broadcast(ev); break; } diff --git a/native/cocos/ui/edit-box/EditBox-win32.cpp b/native/cocos/ui/edit-box/EditBox-win32.cpp index 9addf641c44..c2b416f9635 100644 --- a/native/cocos/ui/edit-box/EditBox-win32.cpp +++ b/native/cocos/ui/edit-box/EditBox-win32.cpp @@ -28,6 +28,7 @@ #include "cocos/bindings/manual/jsb_global.h" #include "cocos/platform/interfaces/modules/ISystemWindow.h" #include "cocos/platform/interfaces/modules/ISystemWindowManager.h" +#include "platform/interfaces/modules/IScreen.h" #include #include @@ -214,16 +215,17 @@ void EditBox::show(const EditBox::ShowInfo &showInfo) { g_prevMainWindowProc = (WNDPROC)SetWindowLongPtr(parent, GWLP_WNDPROC, (LONG_PTR)mainWindowProc); g_prevEditWindowProc = (WNDPROC)SetWindowLongPtr(g_hwndEditBox, GWLP_WNDPROC, (LONG_PTR)editWindowProc); } - + auto *screen = BasePlatform::getPlatform()->getInterface(); + float dpr = screen->getDevicePixelRatio(); ::SendMessageW(g_hwndEditBox, EM_LIMITTEXT, showInfo.maxLength, 0); // SendMessage(g_hwndEditBox, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf); SetWindowPos(g_hwndEditBox, HWND_NOTOPMOST, - showInfo.x, - windowHeight - showInfo.y - showInfo.height, - showInfo.width, - showInfo.height, + showInfo.x * dpr, + windowHeight - showInfo.y * dpr - showInfo.height * dpr, + showInfo.width * dpr, + showInfo.height * dpr, SWP_NOZORDER); ::SetWindowTextW(g_hwndEditBox, str2ws(showInfo.defaultValue).c_str()); @@ -243,7 +245,7 @@ void EditBox::show(const EditBox::ShowInfo &showInfo) { RECT rect; GetWindowRect(getCurrentWindowHwnd(), &rect); - float WindowRatio = (float)(rect.bottom - rect.top) / (float)CC_GET_MAIN_SYSTEM_WINDOW()->getViewSize().height; + float WindowRatio = (float)(rect.bottom - rect.top) / (float)CC_GET_MAIN_SYSTEM_WINDOW()->getViewSize().height * dpr; float JsFontRatio = float(showInfo.fontSize) / 5; /** A probale way to calculate the increase of font size * OriginalSize + Increase = OriginalSize * Ratio_of_js_fontSize * Ratio_of_window