[Ttssh2-commit] [7717] WM_DPICHANGEメッセージのハンドリングを改善

Back to archive index
scmno****@osdn***** scmno****@osdn*****
2019年 5月 30日 (木) 23:27:56 JST


Revision: 7717
          https://osdn.net/projects/ttssh2/scm/svn/commits/7717
Author:   zmatsuo
Date:     2019-05-30 23:27:55 +0900 (Thu, 30 May 2019)
Log Message:
-----------
WM_DPICHANGEメッセージのハンドリングを改善

- r7716 はスムーズにスケーリングできない場合があった
  - OSが提案するウィンドウサイズが、実際のサイズと大きく異なることがある
    - 移動先モニタディスプレイが125%などの拡大率などの場合
    - DPI比率だけでは正しいサイズが算出できない
    - フォントサイズが単純計算で出せない
  - スケーリング後、WM_DPICHANGE再度発生→拡大縮小処理→…ループが発生する
- DPIに合わせて、ウィンドウサイズを計算、DPIが変化しない位置に移動するようにした

Revision Links:
--------------
    https://osdn.net/projects/ttssh2/scm/svn/commits/7716

Modified Paths:
--------------
    trunk/teraterm/common/compat_win.cpp
    trunk/teraterm/common/compat_win.h
    trunk/teraterm/teraterm/vtdisp.c
    trunk/teraterm/teraterm/vtdisp.h
    trunk/teraterm/teraterm/vtwin.cpp
    trunk/teraterm/teraterm/vtwin.h

-------------- next part --------------
Modified: trunk/teraterm/common/compat_win.cpp
===================================================================
--- trunk/teraterm/common/compat_win.cpp	2019-05-28 15:23:02 UTC (rev 7716)
+++ trunk/teraterm/common/compat_win.cpp	2019-05-30 14:27:55 UTC (rev 7717)
@@ -44,6 +44,9 @@
 int (WINAPI *pAddFontResourceExW)(LPCWSTR name, DWORD fl, PVOID res);
 BOOL (WINAPI *pRemoveFontResourceExA)(LPCSTR name, DWORD fl, PVOID pdv);
 BOOL (WINAPI *pRemoveFontResourceExW)(LPCWSTR name, DWORD fl, PVOID pdv);
+HRESULT (WINAPI *pGetDpiForMonitor)(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT *dpiX, UINT *dpiY);
+HMONITOR (WINAPI *pMonitorFromRect)(LPCRECT lprc, DWORD dwFlags);
+BOOL (WINAPI *pAdjustWindowRectExForDpi)(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi);
 
 static const APIInfo Lists_user32[] = {
 	{ "SetLayeredWindowAttributes", (void **)&pSetLayeredWindowAttributes },
@@ -50,6 +53,8 @@
 	{ "SetThreadDpiAwarenessContext", (void **)&pSetThreadDpiAwarenessContext },
 	{ "IsValidDpiAwarenessContext", (void **)&pIsValidDpiAwarenessContext },
 	{ "GetDpiForWindow", (void **)&pGetDpiForWindow },
+	{ "MonitorFromRect", (void **)&pMonitorFromRect },
+	{ "AdjustWindowRectExForDpi", (void **)&pAdjustWindowRectExForDpi },
 	{ NULL },
 };
 
@@ -66,10 +71,16 @@
 	{ NULL },
 };
 
+static const APIInfo Lists_Shcore[] = {
+	{ "GetDpiForMonitor", (void **)&pGetDpiForMonitor },
+	{ NULL },
+};
+
 static const DllInfo DllInfos[] = {
 	{ _T("user32.dll"), DLL_LOAD_LIBRARY_SYSTEM, DLL_ACCEPT_NOT_EXIST, Lists_user32 },
 	{ _T("msimg32.dll"), DLL_LOAD_LIBRARY_SYSTEM, DLL_ACCEPT_NOT_EXIST, Lists_msimg32 },
 	{ _T("gdi32.dll"), DLL_LOAD_LIBRARY_SYSTEM, DLL_ACCEPT_NOT_EXIST, Lists_gdi32 },
+	{ _T("Shcore.dll"), DLL_LOAD_LIBRARY_SYSTEM, DLL_ACCEPT_NOT_EXIST, Lists_Shcore },
 	{ NULL },
 };
 

Modified: trunk/teraterm/common/compat_win.h
===================================================================
--- trunk/teraterm/common/compat_win.h	2019-05-28 15:23:02 UTC (rev 7716)
+++ trunk/teraterm/common/compat_win.h	2019-05-30 14:27:55 UTC (rev 7717)
@@ -48,6 +48,15 @@
 DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
 #endif
 
+#if !defined(DPI_ENUMS_DECLARED)
+typedef enum MONITOR_DPI_TYPE {
+    MDT_EFFECTIVE_DPI = 0,
+    MDT_ANGULAR_DPI = 1,
+    MDT_RAW_DPI = 2,
+    MDT_DEFAULT = MDT_EFFECTIVE_DPI
+} MONITOR_DPI_TYPE;
+#endif
+
 #if !defined(WM_DPICHANGED)
 #define WM_DPICHANGED					0x02E0
 #endif
@@ -60,9 +69,12 @@
 
 extern BOOL (WINAPI *pAlphaBlend)(HDC,int,int,int,int,HDC,int,int,int,int,BLENDFUNCTION);
 extern BOOL (WINAPI *pEnumDisplayMonitors)(HDC,LPCRECT,MONITORENUMPROC,LPARAM);
+extern HMONITOR (WINAPI *pMonitorFromRect)(LPCRECT lprc, DWORD dwFlags);
 extern DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT dpiContext);
 extern BOOL (WINAPI *pIsValidDpiAwarenessContext)(DPI_AWARENESS_CONTEXT dpiContext);
 extern UINT (WINAPI *pGetDpiForWindow)(HWND hwnd);
+extern HRESULT (WINAPI *pGetDpiForMonitor)(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT *dpiX, UINT *dpiY);
+extern BOOL (WINAPI *pAdjustWindowRectExForDpi)(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi);
 extern BOOL (WINAPI *pSetLayeredWindowAttributes)(HWND hwnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags);
 extern int (WINAPI *pAddFontResourceExA)(LPCSTR name, DWORD fl, PVOID res);
 extern int (WINAPI *pAddFontResourceExW)(LPCWSTR name, DWORD fl, PVOID res);

Modified: trunk/teraterm/teraterm/vtdisp.c
===================================================================
--- trunk/teraterm/teraterm/vtdisp.c	2019-05-28 15:23:02 UTC (rev 7716)
+++ trunk/teraterm/teraterm/vtdisp.c	2019-05-30 14:27:55 UTC (rev 7717)
@@ -3899,10 +3899,3 @@
 	}
 	return color;
 }
-
-void DpiChanged(void)
-{
-  ChangeFont();
-  DispChangeWinSize(WinWidth,WinHeight);
-  ChangeCaret();
-}

Modified: trunk/teraterm/teraterm/vtdisp.h
===================================================================
--- trunk/teraterm/teraterm/vtdisp.h	2019-05-28 15:23:02 UTC (rev 7716)
+++ trunk/teraterm/teraterm/vtdisp.h	2019-05-30 14:27:55 UTC (rev 7717)
@@ -116,7 +116,6 @@
 void DispGetRootWinSize(int *x, int *y, BOOL inPixels);
 int DispFindClosestColor(int red, int green, int blue);
 void UpdateBGBrush(void);
-void DpiChanged(void);
 
 extern int WinWidth, WinHeight;
 extern HFONT VTFont[AttrFontMask+1];

Modified: trunk/teraterm/teraterm/vtwin.cpp
===================================================================
--- trunk/teraterm/teraterm/vtwin.cpp	2019-05-28 15:23:02 UTC (rev 7716)
+++ trunk/teraterm/teraterm/vtwin.cpp	2019-05-30 14:27:55 UTC (rev 7717)
@@ -802,6 +802,7 @@
 	FirstPaint = TRUE;
 	ScrollLock = FALSE;  // \x8F\x89\x8A\xFA\x92l\x82͖\xB3\x8C\xF8 (2006.11.14 yutaka)
 	Alpha = 255;
+	IgnoreSizeMessage = FALSE;
 
 	/* Initialize scroll buffer */
 	InitBuffer();
@@ -2769,6 +2770,9 @@
 
 void CVTWindow::OnSize(UINT nType, int cx, int cy)
 {
+	if (IgnoreSizeMessage) {
+		return;
+	}
 	RECT R;
 	int w, h;
 
@@ -6304,16 +6308,99 @@
 	FreeTTDLG();
 }
 
-LRESULT CVTWindow::OnDpiChanged(WPARAM, LPARAM lParam)
+LRESULT CVTWindow::OnDpiChanged(WPARAM wp, LPARAM)
 {
-	const RECT *SuggestedWindowRect = (RECT *)lParam;
-	// \x92\xF1\x88Ă\xB3\x82ꂽ\x88ʒu\x82Ɉړ\xAE\x82\xB7\x82\xE9
-	// \x83T\x83C\x83Y\x82\xCDDpiChange()\x81\xA8DispChangeWinSize()\x82Őݒ肳\x82\xEA\x82\xE9
+	const UINT NewDPI = LOWORD(wp);
+	// \x8C\xBB\x8D݂̃E\x83B\x83\x93\x83h\x83E\x83T\x83C\x83Y
+	RECT CurrentWindowRect;
+	::GetWindowRect(m_hWnd, &CurrentWindowRect);
+	const int CurrentWindowWidth = CurrentWindowRect.right - CurrentWindowRect.left;
+	const int CurrentWindowHeight = CurrentWindowRect.bottom - CurrentWindowRect.top;
+
+	// \x83|\x83C\x83\x93\x83^\x82̈ʒu
+	POINT MouseCursorScreen;
+	GetCursorPos(&MouseCursorScreen);
+	POINT MouseCursorInWindow = MouseCursorScreen;
+	MouseCursorInWindow.x -= CurrentWindowRect.left;
+	MouseCursorInWindow.y -= CurrentWindowRect.top;
+
+	// \x90V\x82\xB5\x82\xA2DPI\x82ɍ\x87\x82킹\x82ăt\x83H\x83\x93\x83g\x82𐶐\xAC\x81A
+	// \x83N\x83\x89\x83C\x83A\x83\x93\x83g\x97̈\xE6\x82̃T\x83C\x83Y\x82\xF0\x8C\x88\x92肷\x82\xE9
+	ChangeFont();
+	ScreenWidth = WinWidth*FontWidth;
+	ScreenHeight = WinHeight*FontHeight;
+	//AdjustScrollBar();
+
+	// \x83X\x83N\x83\x8A\x81[\x83\x93\x83T\x83C\x83Y(=Client Area\x82̃T\x83C\x83Y)\x82\xA9\x82\xE7\x83E\x83B\x83\x93\x83h\x83E\x83T\x83C\x83Y\x82\xF0\x8EZ\x8Fo
+	const LONG_PTR Style = ::GetWindowLongPtr(m_hWnd, GWL_STYLE);
+	const LONG_PTR ExStyle = ::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE);
+	RECT Rect = {0, 0, ScreenWidth, ScreenHeight};
+	pAdjustWindowRectExForDpi(&Rect, Style, TRUE/*menu*/, ExStyle, NewDPI);
+	const int NewWindowWidth = Rect.right - Rect.left;
+	const int NewWindowHeight = Rect.bottom - Rect.top;
+
+	// \x90V\x82\xB5\x82\xA2\x83E\x83B\x83\x93\x83h\x83E\x97̈\xE6\x8C\xF3\x95\xE2
+	RECT NewWindowRect[5];
+
+	// \x83^\x83C\x83g\x83\x8B\x83o\x81[\x8F\xE3\x82̃|\x83C\x83\x93\x83^\x88ʒu\x82\xAA\x82Ȃ\xE9\x82ׂ\xAD\x82\xB8\x82\xEA\x82Ȃ\xA2\x90V\x82\xB5\x82\xA2\x88ʒu
+	int t1 = (int)MouseCursorInWindow.y * (int)NewWindowHeight / (int)CurrentWindowHeight;
+	NewWindowRect[0].top =
+		CurrentWindowRect.top -
+		(t1 - (int)MouseCursorInWindow.y);
+	t1 = (int)MouseCursorInWindow.x * (int)NewWindowWidth / (int)CurrentWindowWidth;
+	NewWindowRect[0].left =
+		CurrentWindowRect.left -
+		(t1 - (int)MouseCursorInWindow.x);
+	NewWindowRect[0].bottom = NewWindowRect[0].top + NewWindowHeight;
+	NewWindowRect[0].right = NewWindowRect[0].left + NewWindowWidth;
+
+	// \x8C\xBB\x8D݈ʒu\x82\xA9\x82\xE7\x8F\xE3\x89E\x8A\xF1\x82\xB9
+	NewWindowRect[1].top = CurrentWindowRect.top;
+	NewWindowRect[1].bottom = CurrentWindowRect.top + NewWindowHeight;
+	NewWindowRect[1].left = CurrentWindowRect.right - NewWindowWidth;
+	NewWindowRect[1].right = CurrentWindowRect.right;
+
+	// \x8C\xBB\x8D݈ʒu\x82\xA9\x82\xE7\x8F㍶\x8A\xF1\x82\xB9
+	NewWindowRect[2].top = CurrentWindowRect.top;
+	NewWindowRect[2].bottom = CurrentWindowRect.top + NewWindowHeight;
+	NewWindowRect[2].left = CurrentWindowRect.left;
+	NewWindowRect[2].right = CurrentWindowRect.left + NewWindowWidth;
+
+	// \x8C\xBB\x8D݈ʒu\x82\xA9\x82牺\x89E\x8A\xF1\x82\xB9
+	NewWindowRect[3].top = CurrentWindowRect.bottom - NewWindowHeight;
+	NewWindowRect[3].bottom = CurrentWindowRect.top;
+	NewWindowRect[3].left = CurrentWindowRect.right - NewWindowWidth;
+	NewWindowRect[3].right = CurrentWindowRect.right;
+
+	// \x8C\xBB\x8D݈ʒu\x82\xA9\x82牺\x8D\xB6\x8A\xF1\x82\xB9
+	NewWindowRect[4].top = CurrentWindowRect.bottom - NewWindowHeight;
+	NewWindowRect[4].bottom = CurrentWindowRect.top;
+	NewWindowRect[4].left = CurrentWindowRect.left;
+	NewWindowRect[4].right = CurrentWindowRect.left + NewWindowWidth;
+
+	// \x8Am\x94F
+	const RECT *NewRect = &NewWindowRect[0];
+	for (int i=0; i < _countof(NewWindowRect); i++) {
+		const RECT *r = &NewWindowRect[i];
+		HMONITOR hMonitor = pMonitorFromRect(r, MONITOR_DEFAULTTONULL);
+		UINT dpiX;
+		UINT dpiY;
+		pGetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
+		if (NewDPI == dpiX) {
+			NewRect = r;
+			break;
+		}
+	}
+
+	IgnoreSizeMessage = TRUE;
 	::SetWindowPos(m_hWnd, NULL,
-				   SuggestedWindowRect->left, SuggestedWindowRect->top,
-				   0, 0,
-				   SWP_NOSIZE | SWP_NOZORDER);
-	DpiChanged();
+				   NewRect->left, NewRect->top,
+				   NewWindowWidth, NewWindowHeight,
+				   SWP_NOZORDER);
+	IgnoreSizeMessage = FALSE;
+
+	ChangeCaret();
+
 	return TRUE;
 }
 

Modified: trunk/teraterm/teraterm/vtwin.h
===================================================================
--- trunk/teraterm/teraterm/vtwin.h	2019-05-28 15:23:02 UTC (rev 7716)
+++ trunk/teraterm/teraterm/vtwin.h	2019-05-30 14:27:55 UTC (rev 7717)
@@ -61,6 +61,9 @@
   BYTE Alpha;
   void SetWindowAlpha(BYTE alpha);
 
+  // DPI
+  BOOL IgnoreSizeMessage;
+
 protected:
 
 public:


Ttssh2-commit メーリングリストの案内
Back to archive index