Browse Source

first pass at per window dpi, changes dynamically to dpi changes

sabrogden 7 years ago
parent
commit
174464f127
33 changed files with 739 additions and 479 deletions
  1. 0 5
      CP_Main.h
  2. 4 1
      CP_Main.vcxproj
  3. 2 0
      CP_Main.vcxproj.filters
  4. 2 0
      DPI.h
  5. 9 3
      DeclareDPIAware.manifest
  6. 2 2
      DittoPopupWindow.cpp
  7. 165 257
      DittoWindow.cpp
  8. 10 12
      DittoWindow.h
  9. 36 5
      EditFrameWnd.cpp
  10. 6 1
      EditFrameWnd.h
  11. 17 13
      GdiImageDrawer.cpp
  12. 8 5
      GdiImageDrawer.h
  13. 12 8
      GdipButton.cpp
  14. 1 1
      GdipButton.h
  15. 0 13
      MainFrm.cpp
  16. 1 1
      Options.cpp
  17. 26 4
      OptionsGeneral.cpp
  18. 2 6
      OptionsGeneral.h
  19. 1 1
      OptionsQuickPaste.cpp
  20. 82 57
      QListCtrl.cpp
  21. 10 2
      QListCtrl.h
  22. 103 41
      QPasteWnd.cpp
  23. 2 1
      QPasteWnd.h
  24. 51 9
      QRCodeViewer.cpp
  25. 7 0
      QRCodeViewer.h
  26. 15 0
      QuickPaste.cpp
  27. 2 2
      StdAfx.h
  28. 47 10
      SymbolEdit.cpp
  29. 7 0
      SymbolEdit.h
  30. 68 15
      ToolTipEx.cpp
  31. 6 0
      ToolTipEx.h
  32. 29 3
      WndEx.cpp
  33. 6 1
      WndEx.h

+ 0 - 5
CP_Main.h

@@ -20,14 +20,10 @@
 #include "DittoAddins.h"
 #include "externalwindowtracker.h"
 #include "HotKeys.h"
-#include "DPI.h"
 #include "UAC_Thread.h"
 
 extern class CCP_MainApp theApp;
 
-#define BORDER theApp.m_metrics.ScaleX(2) 
-#define CAPTION_BORDER theApp.m_metrics.ScaleX(25)
-
 class CCP_MainApp : public CWinApp
 {
 public:
@@ -177,7 +173,6 @@ public:
 
 	CDittoAddins m_Addins;
 
-	CDPI m_metrics;
 	ULONG_PTR m_gdiplusToken;
 
 	bool UACPaste();

+ 4 - 1
CP_Main.vcxproj

@@ -22,7 +22,7 @@
     <RootNamespace>CP_Main</RootNamespace>
     <Keyword>MFCProj</Keyword>
     <ProjectGuid>{8ECC3EF2-AF07-27B6-A773-779874943C0D}</ProjectGuid>
-    <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
+    <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -280,6 +280,7 @@
     </PostBuildEvent>
     <Manifest>
       <AdditionalManifestFiles>DeclareDPIAware.manifest</AdditionalManifestFiles>
+      <EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
     </Manifest>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -650,6 +651,7 @@
     <ClCompile Include="Shared\TextConvert.cpp" />
     <ClCompile Include="Shared\Tokenizer.cpp" />
     <ClCompile Include="ShowTaskBarIcon.cpp" />
+    <ClCompile Include="SnapWindow.cpp" />
     <ClCompile Include="SpecialPasteOptions.cpp" />
     <ClCompile Include="sqlite\CppSQLite3.cpp">
       <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Disabled</Optimization>
@@ -1920,6 +1922,7 @@
     <ClInclude Include="Shared\TextConvert.h" />
     <ClInclude Include="Shared\Tokenizer.h" />
     <ClInclude Include="ShowTaskBarIcon.h" />
+    <ClInclude Include="SnapWindow.h" />
     <ClInclude Include="SpecialPasteOptions.h" />
     <ClInclude Include="sqlite\sqlite3.h" />
     <ClInclude Include="sqlite\sqlite3ext.h" />

+ 2 - 0
CP_Main.vcxproj.filters

@@ -441,6 +441,7 @@
     <ClCompile Include="DittoChaiScript.cpp">
       <Filter>ChaiScript</Filter>
     </ClCompile>
+    <ClCompile Include="SnapWindow.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="sqlite\CppSQLite3.h">
@@ -922,6 +923,7 @@
     <ClInclude Include="DittoChaiScript.h">
       <Filter>ChaiScript</Filter>
     </ClInclude>
+    <ClInclude Include="SnapWindow.h" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="CP_Main.rc">

+ 2 - 0
DPI.h

@@ -5,6 +5,8 @@ class CDPI
 public:
 	CDPI() : _fInitialized(false), _dpiX(96), _dpiY(96) { }
 
+	void Update(int dpi) { _dpiX = dpi; _dpiY = dpi; }
+
 	// Get screen DPI.
 	int GetDPIX() { _Init(); return _dpiX; }
 	int GetDPIY() { _Init(); return _dpiY; }

+ 9 - 3
DeclareDPIAware.manifest

@@ -1,7 +1,13 @@
-<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
+ 
   <asmv3:application>
-    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
-      <dpiAware>true</dpiAware>
+    <asmv3:windowsSettings>
+      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
+      <!-- fallback for Windows 7 and 8 -->
+      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness>
+      <!-- falls back to per-monitor if per-monitor v2 is not supported -->
+      
+      <!-- enables GDI DPI scaling -->
     </asmv3:windowsSettings>
   </asmv3:application>
 </assembly>

+ 2 - 2
DittoPopupWindow.cpp

@@ -28,8 +28,8 @@ int CDittoPopupWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
 	}
 
 	CWndEx::SetCaptionOn(CAPTION_TOP, false, g_Opt.m_Theme.GetCaptionSize(), g_Opt.m_Theme.GetCaptionFontSize());
-
-	m_font.CreateFont(-theApp.m_metrics.PointsToPixels(12), 0, 0, 0, 400, 0, 0, 0, DEFAULT_CHARSET, 3, 2, 1, 34, _T("MS Sans Serif"));
+		
+	m_font.CreateFont(-m_DittoWindow.m_dpi.PointsToPixels(12), 0, 0, 0, 400, 0, 0, 0, DEFAULT_CHARSET, 3, 2, 1, 34, _T("MS Sans Serif"));
 	m_textLabel.Create(_T("test"), WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), this);
 	m_textLabel.SetFont(&m_font);
 	

+ 165 - 257
DittoWindow.cpp

@@ -6,12 +6,9 @@
 
 CDittoWindow::CDittoWindow(void)
 {
-	m_captionBorderWidth = theApp.m_metrics.ScaleX(25);
+	m_captionBorderWidth = m_dpi.ScaleX(25);
 
-	m_lTopBorder = m_captionBorderWidth;
-	m_lRightBorder = BORDER;
-	m_lBottomBorder = BORDER;
-	m_lLeftBorder = BORDER;
+	m_borderSize = 2;
 	m_bMouseOverChevron = false;
 	m_bMouseDownOnChevron = false;
 	m_bMouseDownOnClose = false;
@@ -38,6 +35,8 @@ CDittoWindow::CDittoWindow(void)
 	m_useCustomWindowTitle = false;
 	m_buttonDownOnCaption = false;
 	m_crFullSizeWindow.SetRectEmpty();	
+	m_captionPosition = CAPTION_RIGHT;
+	
 }
 
 CDittoWindow::~CDittoWindow(void)
@@ -46,31 +45,51 @@ CDittoWindow::~CDittoWindow(void)
 
 void CDittoWindow::DoCreate(CWnd *pWnd)
 {
-	m_VertFont.CreateFont(theApp.m_metrics.PointsToPixels(18), 0, -900, 0, 400, FALSE, FALSE, 0, DEFAULT_CHARSET,
+	//EnableNonClientDpiScaling(pWnd->m_hWnd);
+
+	int dpi = GetDpiForWindow(pWnd->m_hWnd);
+	m_dpi.Update(dpi);
+
+	m_VertFont.CreateFont(m_dpi.PointsToPixels(18), 0, -900, 0, 400, FALSE, FALSE, 0, DEFAULT_CHARSET,
 							OUT_DEFAULT_PRECIS,	CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, 
 							DEFAULT_PITCH|FF_SWISS, _T("Segoe UI"));
 
-	m_HorFont.CreateFont(theApp.m_metrics.PointsToPixels(18), 0, 0, 0, 500, FALSE, FALSE, 0, DEFAULT_CHARSET,
+	m_HorFont.CreateFont(m_dpi.PointsToPixels(18), 0, 0, 0, 500, FALSE, FALSE, 0, DEFAULT_CHARSET,
 						OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
 						DEFAULT_PITCH|FF_SWISS, _T("Segoe UI"));
 
 	SetTitleTextHeight(pWnd);
 	
-	m_closeButton.LoadStdImageDPI(Close_Black_16_16, Close_Black_20_20, Close_Black_24_24, Close_Black_28, Close_Black_32_32, _T("PNG"));
-	m_chevronRightButton.LoadStdImageDPI(ChevronRight_Black_16_16, ChevronRight_Black_20_20, ChevronRight_Black_24_24, ChevronRight_Black_28, ChevronRight_Black_32_32, _T("PNG"));
-	m_chevronLeftButton.LoadStdImageDPI(ChevronLeft_Black_16_16, ChevronLeft_Black_20_20, ChevronLeft_Black_24_24, ChevronLeft_Black_28, ChevronLeft_Black_32_32, _T("PNG"));
-	m_maximizeButton.LoadStdImageDPI(IDB_MAXIMIZE_16_16, maximize_20, maximize_24, maximize_28, maximize_32, _T("PNG"));
-	m_minimizeButton.LoadStdImageDPI(minimize_16, minimize_20, minimize_24, minimize_28, minimize_32, _T("PNG"));
+	m_closeButton.LoadStdImageDPI(m_dpi.GetDPIX(), Close_Black_16_16, Close_Black_20_20, Close_Black_24_24, Close_Black_28, Close_Black_32_32, _T("PNG"));
+	m_chevronRightButton.LoadStdImageDPI(m_dpi.GetDPIX(), ChevronRight_Black_16_16, ChevronRight_Black_20_20, ChevronRight_Black_24_24, ChevronRight_Black_28, ChevronRight_Black_32_32, _T("PNG"));
+	m_chevronLeftButton.LoadStdImageDPI(m_dpi.GetDPIX(), ChevronLeft_Black_16_16, ChevronLeft_Black_20_20, ChevronLeft_Black_24_24, ChevronLeft_Black_28, ChevronLeft_Black_32_32, _T("PNG"));
+	m_maximizeButton.LoadStdImageDPI(m_dpi.GetDPIX(), IDB_MAXIMIZE_16_16, maximize_20, maximize_24, maximize_28, maximize_32, _T("PNG"));
+	m_minimizeButton.LoadStdImageDPI(m_dpi.GetDPIX(), minimize_16, minimize_20, minimize_24, minimize_28, minimize_32, _T("PNG"));
 	//m_windowIcon.LoadStdImageDPI(NewWindowIcon_24_14, NewWindowIcon_30, NewWindowIcon_36, NewWindowIcon_48, _T("PNG"));
 }
 
 void CDittoWindow::DoNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
 {
-	//Decrease the client area
-	lpncsp->rgrc[0].left += m_lLeftBorder;
-	lpncsp->rgrc[0].top += m_lTopBorder;
-	lpncsp->rgrc[0].right -= m_lRightBorder;
-	lpncsp->rgrc[0].bottom -= m_lBottomBorder;
+	//Decrease the client area	
+	if (m_captionPosition == CAPTION_LEFT)
+		lpncsp->rgrc[0].left += m_captionBorderWidth;
+	else
+		lpncsp->rgrc[0].left += m_borderSize;
+
+	if (m_captionPosition == CAPTION_TOP)
+		lpncsp->rgrc[0].top += m_captionBorderWidth;
+	else
+		lpncsp->rgrc[0].top += m_borderSize;
+
+	if (m_captionPosition == CAPTION_RIGHT)
+		lpncsp->rgrc[0].right -= m_captionBorderWidth;
+	else
+		lpncsp->rgrc[0].right -= m_borderSize;
+
+	if (m_captionPosition == CAPTION_BOTTOM)
+		lpncsp->rgrc[0].bottom -= m_captionBorderWidth;
+	else
+		lpncsp->rgrc[0].bottom -= m_borderSize;
 }
 
 UINT CDittoWindow::DoNcHitTest(CWnd *pWnd, CPoint point) 
@@ -100,115 +119,115 @@ UINT CDittoWindow::DoNcHitTest(CWnd *pWnd, CPoint point)
 
 	if(m_bMinimized == false)
 	{
-		if ((point.y < crWindow.top + BORDER * 4) &&
-			(point.x < crWindow.left + BORDER * 4))
+		if ((point.y < crWindow.top + m_borderSize * 4) &&
+			(point.x < crWindow.left + m_borderSize * 4))
 			return HTTOPLEFT;
-		else if ((point.y < crWindow.top + BORDER * 4) &&
-			(point.x > crWindow.right - BORDER * 4))
+		else if ((point.y < crWindow.top + m_borderSize * 4) &&
+			(point.x > crWindow.right - m_borderSize * 4))
 			return HTTOPRIGHT;
-		else if ((point.y > crWindow.bottom - BORDER * 4) &&
-			(point.x > crWindow.right - BORDER * 4))
+		else if ((point.y > crWindow.bottom - m_borderSize * 4) &&
+			(point.x > crWindow.right - m_borderSize * 4))
 			return HTBOTTOMRIGHT;
-		else if ((point.y > crWindow.bottom - BORDER * 4) &&
-			(point.x < crWindow.left + BORDER * 4))
+		else if ((point.y > crWindow.bottom - m_borderSize * 4) &&
+			(point.x < crWindow.left + m_borderSize * 4))
 			return HTBOTTOMLEFT;
 	}
 
-	if((((m_lTopBorder == m_captionBorderWidth) || (m_lBottomBorder == m_captionBorderWidth)) &&
+	if((((m_captionPosition == CAPTION_TOP) || (m_captionPosition == CAPTION_BOTTOM)) &&
 		(m_bMinimized)) == false)
 	{
-		if (point.y < crWindow.top + BORDER * 2)
+		if (point.y < crWindow.top + m_borderSize * 2)
 			return HTTOP;
-		if (point.y > crWindow.bottom - BORDER * 2)
+		if (point.y > crWindow.bottom - m_borderSize * 2)
 			return HTBOTTOM;
 	}
 
-	if((((m_lLeftBorder == m_captionBorderWidth) || (m_lRightBorder == m_captionBorderWidth)) &&
+	if((((m_captionPosition == CAPTION_LEFT) || (m_captionPosition == CAPTION_RIGHT)) &&
 		(m_bMinimized)) == false)
 	{
-		if (point.x > crWindow.right - BORDER * 2)
+		if (point.x > crWindow.right - m_borderSize * 2)
 			return HTRIGHT;
-		if (point.x < crWindow.left + BORDER * 2)
+		if (point.x < crWindow.left + m_borderSize * 2)
 			return HTLEFT;
 	}
 
-	if(m_lRightBorder == m_captionBorderWidth)
+	if (m_captionPosition == CAPTION_RIGHT)
 	{
-		if (point.x > crWindow.right - m_lRightBorder)
+		if (point.x > crWindow.right - m_captionBorderWidth)
 			return HTCAPTION;
 	}
-	else if(m_lBottomBorder == m_captionBorderWidth)
+	if (m_captionPosition == CAPTION_BOTTOM)
 	{
-		if(point.y > crWindow.bottom - m_lBottomBorder)
+		if(point.y > crWindow.bottom - m_captionBorderWidth)
 			return HTCAPTION;
 	}
-	else if(m_lLeftBorder == m_captionBorderWidth)
+	if (m_captionPosition == CAPTION_LEFT)
 	{
-		if (point.x < crWindow.left + m_lLeftBorder)
+		if (point.x < crWindow.left + m_captionBorderWidth)
 			return HTCAPTION;
 	}
-	else if(m_lTopBorder == m_captionBorderWidth)
+	if (m_captionPosition == CAPTION_TOP)
 	{
-		if (point.y < crWindow.top + m_lTopBorder)
+		if (point.y < crWindow.top + m_captionBorderWidth)
 			return HTCAPTION;
 	}
 
 	return -1;
 }
 
-int IndexToPos(int index, bool horizontal)
+int CDittoWindow::IndexToPos(int index, bool horizontal)
 {
 	switch (index)
 	{
 	case 0:
 		if (horizontal)
 		{
-			return theApp.m_metrics.ScaleX(24);
+			return m_dpi.ScaleX(24);
 		}
 		else
 		{
-			return theApp.m_metrics.ScaleY(8);
+			return m_dpi.ScaleY(8);
 		}
 		break;
 	case 1:
 		if (horizontal)
 		{
-			return theApp.m_metrics.ScaleX(48);
+			return m_dpi.ScaleX(48);
 		}
 		else
 		{
-			return theApp.m_metrics.ScaleY(32);
+			return m_dpi.ScaleY(32);
 		}
 		break;
 	case 2:
 
 		if (horizontal)
 		{
-			return theApp.m_metrics.ScaleX(72);
+			return m_dpi.ScaleX(72);
 		}
 		else
 		{
-			return theApp.m_metrics.ScaleY(56);
+			return m_dpi.ScaleY(56);
 		}
 		break;
 	case 3:
 		if (horizontal)
 		{
-			return theApp.m_metrics.ScaleX(96);
+			return m_dpi.ScaleX(96);
 		}
 		else
 		{
-			return theApp.m_metrics.ScaleY(80);
+			return m_dpi.ScaleY(80);
 		}
 		break;
 	case 4:
 		if (horizontal)
 		{
-			return theApp.m_metrics.ScaleX(104);
+			return m_dpi.ScaleX(104);
 		}
 		else
 		{
-			return theApp.m_metrics.ScaleY(104);
+			return m_dpi.ScaleY(104);
 		}
 		break;
 	}
@@ -233,8 +252,8 @@ void CDittoWindow::DoNcPaint(CWnd *pWnd)
 	// Draw the window border
 	CRect rcBorder(0, 0, lWidth, rcFrame.Height());
 
-	int border = theApp.m_metrics.ScaleX(2);
-	int widthHeight = theApp.m_metrics.ScaleX(16);
+	int border = m_dpi.ScaleX(2);
+	int widthHeight = m_dpi.ScaleX(16);
 
 	for (int x = 0; x < border; x++)
 	{
@@ -251,22 +270,22 @@ void CDittoWindow::DoNcPaint(CWnd *pWnd)
 
 	if (m_bDrawClose)
 	{
-		iconArea += theApp.m_metrics.ScaleX(32);
+		iconArea += m_dpi.ScaleX(32);
 		closeIndex = index++;
 	}
 	if (m_bDrawChevron)
 	{
-		iconArea += theApp.m_metrics.ScaleX(32);
+		iconArea += m_dpi.ScaleX(32);
 		chevronIndex = index++;
 	}
 	if (m_bDrawMaximize)
 	{
-		iconArea += theApp.m_metrics.ScaleX(32);
+		iconArea += m_dpi.ScaleX(32);
 		maxIndex = index++;
 	}
 	if (m_bDrawMinimize)
 	{
-		iconArea += theApp.m_metrics.ScaleX(32);
+		iconArea += m_dpi.ScaleX(32);
 		minIndex = index++;
 	}
 	
@@ -275,12 +294,12 @@ void CDittoWindow::DoNcPaint(CWnd *pWnd)
 	CRect textRect;	
 
 	BOOL bVertical = FALSE;
-	if(m_lRightBorder == m_captionBorderWidth)
+	if(m_captionPosition == CAPTION_RIGHT)
 	{
 		rightRect.SetRect(rcBorder.right - (m_captionBorderWidth - border), rcBorder.top, rcBorder.right, rcBorder.top + IndexToPos(index, false));
 		leftRect.SetRect(rcBorder.right - (m_captionBorderWidth - border), rcBorder.top + IndexToPos(index, false), rcBorder.right, rcBorder.bottom);
 		
-		textRect.SetRect(rcBorder.right, rightRect.bottom + theApp.m_metrics.ScaleX(10), rcBorder.right - m_captionBorderWidth, rcBorder.bottom - theApp.m_metrics.ScaleX(1));
+		textRect.SetRect(rcBorder.right, rightRect.bottom + m_dpi.ScaleX(10), rcBorder.right - m_captionBorderWidth, rcBorder.bottom - m_dpi.ScaleX(1));
 
 		int left = rightRect.left;
 		int right = rightRect.right;
@@ -298,16 +317,16 @@ void CDittoWindow::DoNcPaint(CWnd *pWnd)
 		m_crMinimizeBT.SetRect(left, top, right, top + widthHeight);
 
 
-		m_crWindowIconBT.SetRect(rcBorder.right - theApp.m_metrics.ScaleX(24), rcBorder.bottom - theApp.m_metrics.ScaleX(28), rcBorder.right - theApp.m_metrics.ScaleX(2), rcBorder.bottom);
+		m_crWindowIconBT.SetRect(rcBorder.right - m_dpi.ScaleX(24), rcBorder.bottom - m_dpi.ScaleX(28), rcBorder.right - m_dpi.ScaleX(2), rcBorder.bottom);
 
 		bVertical = TRUE;
 	}
-	else if(m_lLeftBorder == m_captionBorderWidth)
+	if (m_captionPosition == CAPTION_LEFT)
 	{
 		rightRect.SetRect(rcBorder.left, rcBorder.top, rcBorder.left + m_captionBorderWidth - border, rcBorder.top + IndexToPos(index, false));
 		leftRect.SetRect(rcBorder.left, rcBorder.top + IndexToPos(index, false), rcBorder.left + m_captionBorderWidth - border, rcBorder.bottom);
 
-		textRect.SetRect(rcBorder.left + m_captionBorderWidth - theApp.m_metrics.ScaleX(0), rightRect.bottom + theApp.m_metrics.ScaleX(10), rcBorder.left - theApp.m_metrics.ScaleX(5), rcBorder.bottom - theApp.m_metrics.ScaleX(1));
+		textRect.SetRect(rcBorder.left + m_captionBorderWidth - m_dpi.ScaleX(0), rightRect.bottom + m_dpi.ScaleX(10), rcBorder.left - m_dpi.ScaleX(5), rcBorder.bottom - m_dpi.ScaleX(1));
 
 		int left = rightRect.left;
 		int right = rightRect.right;
@@ -324,13 +343,13 @@ void CDittoWindow::DoNcPaint(CWnd *pWnd)
 		top = IndexToPos(minIndex, false);
 		m_crMinimizeBT.SetRect(left, top, right, top + widthHeight);
 
-		m_crWindowIconBT.SetRect(rcBorder.left + theApp.m_metrics.ScaleX(0), rcBorder.bottom - theApp.m_metrics.ScaleX(28), rcBorder.left + theApp.m_metrics.ScaleX(25), rcBorder.bottom);
+		m_crWindowIconBT.SetRect(rcBorder.left + m_dpi.ScaleX(0), rcBorder.bottom - m_dpi.ScaleX(28), rcBorder.left + m_dpi.ScaleX(25), rcBorder.bottom);
 
 		bVertical = TRUE;
 	}
-	else if(m_lTopBorder == m_captionBorderWidth)
+	if (m_captionPosition == CAPTION_TOP)
 	{
-		leftRect.SetRect(rcBorder.left, rcBorder.top, rcBorder.right - IndexToPos(index-1, true)- theApp.m_metrics.ScaleX(8), m_captionBorderWidth);
+		leftRect.SetRect(rcBorder.left, rcBorder.top, rcBorder.right - IndexToPos(index-1, true)- m_dpi.ScaleX(8), m_captionBorderWidth);
 		rightRect.SetRect(leftRect.right, rcBorder.top, rcBorder.right, m_captionBorderWidth);
 
 		textRect.SetRect(leftRect.right, leftRect.top, leftRect.right, leftRect.bottom);
@@ -349,14 +368,14 @@ void CDittoWindow::DoNcPaint(CWnd *pWnd)
 		
 		left = rcBorder.right - IndexToPos(minIndex, true);
 		m_crMinimizeBT.SetRect(left, top, left + widthHeight, bottom);
-				left = rcBorder.left + theApp.m_metrics.ScaleX(10);
-		m_crWindowIconBT.SetRect(left, top, left + theApp.m_metrics.ScaleX(24), bottom);
+				left = rcBorder.left + m_dpi.ScaleX(10);
+		m_crWindowIconBT.SetRect(left, top, left + m_dpi.ScaleX(24), bottom);
 		
 		bVertical = FALSE;
 	}
-	else if(m_lBottomBorder == m_captionBorderWidth)
+	if (m_captionPosition == CAPTION_BOTTOM)
 	{
-		leftRect.SetRect(rcBorder.left, rcBorder.bottom- m_captionBorderWidth - border, rcBorder.right - IndexToPos(index - 1, true) - theApp.m_metrics.ScaleX(8), rcBorder.bottom);
+		leftRect.SetRect(rcBorder.left, rcBorder.bottom- m_captionBorderWidth - border, rcBorder.right - IndexToPos(index - 1, true) - m_dpi.ScaleX(8), rcBorder.bottom);
 		rightRect.SetRect(leftRect.right, rcBorder.bottom - m_captionBorderWidth - border, rcBorder.right, rcBorder.bottom);
 
 		textRect.SetRect(leftRect.right, leftRect.top, leftRect.right, leftRect.bottom);
@@ -376,8 +395,8 @@ void CDittoWindow::DoNcPaint(CWnd *pWnd)
 		left = rcBorder.right - IndexToPos(minIndex, true);
 		m_crMinimizeBT.SetRect(left, top, left + widthHeight, bottom);
 
-		left = rcBorder.left + theApp.m_metrics.ScaleX(10);
-		m_crWindowIconBT.SetRect(left, top, left + theApp.m_metrics.ScaleX(24), bottom);
+		left = rcBorder.left + m_dpi.ScaleX(10);
+		m_crWindowIconBT.SetRect(left, top, left + m_dpi.ScaleX(24), bottom);
 
 		bVertical = FALSE;
 	}
@@ -413,7 +432,7 @@ void CDittoWindow::DoNcPaint(CWnd *pWnd)
 	{
 		CRect size(0, 0, 0, 0);
 		dc.DrawText(csText, size, DT_CALCRECT);
-		textRect.left = textRect.right - size.Width() - theApp.m_metrics.ScaleX(10);
+		textRect.left = textRect.right - size.Width() - m_dpi.ScaleX(10);
 
 		flags |= DT_VCENTER;
 	}
@@ -426,7 +445,7 @@ void CDittoWindow::DoNcPaint(CWnd *pWnd)
 		int offset = rectWidth / 2 - m_titleTextHeight / 2;
 		//textRect.right += 30;
 		//I don't understand where the 4 is coming from but it's always 4 pixals from the right so adjust for this
-		textRect.left -= (offset - theApp.m_metrics.ScaleX(4));		
+		textRect.left -= (offset - m_dpi.ScaleX(4));		
 
 		int k = 0;
 	}
@@ -443,71 +462,6 @@ void CDittoWindow::DoNcPaint(CWnd *pWnd)
 	DrawMinimizeBtn(dc, pWnd);
 }
 
-void CDittoWindow::DoSetRegion(CWnd *pWnd)
-{
-	return;
-	//Create the region for drawing the rounded top edge
-
-	CRect rect;
-	CRgn rgnRect, rgnRect2, rgnRound, rgnFinalA, rgnFinalB;
-	pWnd->GetWindowRect(rect);
-
-	if(rect.Width() < 0)
-		return;
-
-	CRect r;
-	pWnd->GetClientRect(&r);
-
-	int seven = theApp.m_metrics.ScaleX(7);
-	int fifteen = theApp.m_metrics.ScaleX(15);
-	int one = theApp.m_metrics.ScaleX(1);
-	
-	if((m_lRightBorder == m_captionBorderWidth) ||
-		(m_lTopBorder == m_captionBorderWidth))
-	{		
-		rgnRect.CreateRectRgn(0, 0, rect.Width() - seven, rect.Height());
-		rgnRound.CreateRoundRectRgn(0, 0, rect.Width() + one, rect.Height(), fifteen, fifteen);
-
-		rgnFinalB.CreateRectRgn(0, 0, 0, 0);
-		rgnFinalB.CombineRgn(&rgnRect, &rgnRound, RGN_OR);
-
-		rgnRect2.CreateRectRgn(0, seven, rect.Width(), rect.Height());
-		rgnFinalA.CreateRectRgn(0, 0, 0, 0);
-		rgnFinalA.CombineRgn(&rgnRect2, &rgnFinalB, RGN_OR);
-
-		//Set the region
-		pWnd->SetWindowRgn(rgnFinalA, TRUE);
-	}
-	else if(m_lLeftBorder == m_captionBorderWidth)
-	{
-		rgnRect.CreateRectRgn(0, seven, rect.Width(), rect.Height());
-		rgnRound.CreateRoundRectRgn(0, 0, rect.Width(), rect.Height(), fifteen, fifteen);
-
-		rgnFinalB.CreateRectRgn(0, 0, 0, 0);
-		rgnFinalB.CombineRgn(&rgnRect, &rgnRound, RGN_OR);
-
-		rgnRect2.CreateRectRgn(seven, 0, rect.Width(), rect.Height());
-		rgnFinalA.CreateRectRgn(0, 0, 0, 0);
-		rgnFinalA.CombineRgn(&rgnRect2, &rgnFinalB, RGN_OR);
-
-		pWnd->SetWindowRgn(rgnFinalA, TRUE);
-	}
-	else if(m_lBottomBorder == m_captionBorderWidth)
-	{
-		rgnRect.CreateRectRgn(0, 0, rect.Width(), rect.Height() - seven);
-		rgnRound.CreateRoundRectRgn(0, 0, rect.Width() + one, rect.Height() + one, fifteen, fifteen);
-
-		rgnFinalB.CreateRectRgn(0, 0, 0, 0);
-		rgnFinalB.CombineRgn(&rgnRect, &rgnRound, RGN_OR);
-
-		rgnRect2.CreateRectRgn(0, 0, rect.Width() - fifteen, rect.Height());
-		rgnFinalA.CreateRectRgn(0, 0, 0, 0);
-		rgnFinalA.CombineRgn(&rgnRect2, &rgnFinalB, RGN_OR);
-
-		pWnd->SetWindowRgn(rgnFinalA, TRUE);
-	}
-}
-
 void CDittoWindow::DrawChevronBtn(CWindowDC &dc, CWnd *pWnd)
 {
 	if(m_bDrawChevron == false)
@@ -517,11 +471,11 @@ void CDittoWindow::DrawChevronBtn(CWindowDC &dc, CWnd *pWnd)
 		
 	if(this->m_bMinimized)
 	{
-		m_chevronLeftButton.Draw(&dc, pWnd, m_crChevronBT, m_bMouseOverChevron, m_bMouseDownOnChevron);
+		m_chevronLeftButton.Draw(&dc, m_dpi, pWnd, m_crChevronBT, m_bMouseOverChevron, m_bMouseDownOnChevron);
 	}
 	else
 	{
-		m_chevronRightButton.Draw(&dc, pWnd, m_crChevronBT, m_bMouseOverChevron, m_bMouseDownOnChevron);
+		m_chevronRightButton.Draw(&dc, m_dpi, pWnd, m_crChevronBT, m_bMouseOverChevron, m_bMouseDownOnChevron);
 	}
 }
 
@@ -537,7 +491,7 @@ void CDittoWindow::DrawCloseBtn(CWindowDC &dc, CWnd *pWnd)
 		return;
 	}
 	
-	m_closeButton.Draw(&dc, pWnd, m_crCloseBT, m_bMouseOverClose, m_bMouseDownOnClose);
+	m_closeButton.Draw(&dc, m_dpi, pWnd, m_crCloseBT, m_bMouseOverClose, m_bMouseDownOnClose);
 }
 
 void CDittoWindow::DrawMinimizeBtn(CWindowDC &dc, CWnd *pWnd)
@@ -547,7 +501,7 @@ void CDittoWindow::DrawMinimizeBtn(CWindowDC &dc, CWnd *pWnd)
 		return;
 	}
 
-	m_minimizeButton.Draw(&dc, pWnd, m_crMinimizeBT, m_bMouseOverMinimize, m_bMouseDownOnMinimize);
+	m_minimizeButton.Draw(&dc, m_dpi, pWnd, m_crMinimizeBT, m_bMouseOverMinimize, m_bMouseDownOnMinimize);
 }
 
 void CDittoWindow::DrawMaximizeBtn(CWindowDC &dc, CWnd *pWnd)
@@ -557,7 +511,7 @@ void CDittoWindow::DrawMaximizeBtn(CWindowDC &dc, CWnd *pWnd)
 		return;
 	}
 
-	m_maximizeButton.Draw(&dc, pWnd, m_crMaximizeBT, m_bMouseOverMaximize, m_bMouseDownOnMaximize);
+	m_maximizeButton.Draw(&dc, m_dpi, pWnd, m_crMaximizeBT, m_bMouseOverMaximize, m_bMouseDownOnMaximize);
 }
 
 int CDittoWindow::DoNcLButtonDown(CWnd *pWnd, UINT nHitTest, CPoint point) 
@@ -576,8 +530,23 @@ int CDittoWindow::DoNcLButtonDown(CWnd *pWnd, UINT nHitTest, CPoint point)
 	CPoint clPoint(point);
 	pWnd->ScreenToClient(&clPoint);
 
-	clPoint.x += m_lLeftBorder;
-	clPoint.y += m_lTopBorder;
+	if (m_captionPosition == CAPTION_LEFT)
+	{
+		clPoint.x += m_captionBorderWidth;
+	}
+	else
+	{
+		clPoint.x += m_borderSize;
+	}
+
+	if (m_captionPosition == CAPTION_TOP)
+	{
+		clPoint.y += m_captionBorderWidth;
+	}
+	else
+	{
+		clPoint.y += m_borderSize;
+	}	
 
 	if(m_crCloseBT.PtInRect(clPoint))
 	{
@@ -748,36 +717,22 @@ bool CDittoWindow::DoPreTranslateMessage(MSG* pMsg)
 void CDittoWindow::SetCaptionOn(CWnd *pWnd, int nPos, bool bOnstartup, int captionSize, int captionFontSize)
 {
 	m_VertFont.Detach();
-	m_VertFont.CreateFont(theApp.m_metrics.PointsToPixels(captionFontSize), 0, -900, 0, 400, FALSE, FALSE, 0, DEFAULT_CHARSET,
+	m_VertFont.CreateFont(m_dpi.PointsToPixels(captionFontSize), 0, -900, 0, 400, FALSE, FALSE, 0, DEFAULT_CHARSET,
 		OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
 		DEFAULT_PITCH | FF_SWISS, _T("Segoe UI"));
 
 	m_HorFont.Detach();
-	m_HorFont.CreateFont(theApp.m_metrics.PointsToPixels(captionFontSize), 0, 0, 0, 500, FALSE, FALSE, 0, DEFAULT_CHARSET,
+	m_HorFont.CreateFont(m_dpi.PointsToPixels(captionFontSize), 0, 0, 0, 500, FALSE, FALSE, 0, DEFAULT_CHARSET,
 		OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
 		DEFAULT_PITCH | FF_SWISS, _T("Segoe UI"));
 
 	SetTitleTextHeight(pWnd);
 
-	m_lTopBorder = BORDER;
-	m_lRightBorder = BORDER;
-	m_lBottomBorder = BORDER;
-	m_lLeftBorder = BORDER;
+	m_captionPosition = nPos;
 
 	int oldWidth = m_captionBorderWidth;
-	m_captionBorderWidth = theApp.m_metrics.ScaleX(captionSize);	
-
-	if(nPos == CAPTION_RIGHT)
-		m_lRightBorder = m_captionBorderWidth;
-	if(nPos == CAPTION_BOTTOM)
-		m_lBottomBorder = m_captionBorderWidth;
-	if(nPos == CAPTION_LEFT)
-		m_lLeftBorder = m_captionBorderWidth;
-	if(nPos == CAPTION_TOP)
-		m_lTopBorder = m_captionBorderWidth;
-
-	DoSetRegion(pWnd);
-
+	m_captionBorderWidth = m_dpi.ScaleX(captionSize);	
+		
 	if(!bOnstartup)
 	{
 		pWnd->SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
@@ -816,96 +771,6 @@ void CDittoWindow::SetCaptionTextColor(COLORREF color)
 	m_CaptionTextColor = color;
 }
 
-void CDittoWindow::SnapToEdge(CWnd *pWnd, WINDOWPOS* lpwndpos)
-{
-	if (lpwndpos->cx == 0 &&
-		lpwndpos->cy == 0)
-	{
-		return;
-	}
-
-	const char threshold = 12;
-	RECT rect = { 0 };
-	HMONITOR hMonitor;
-	MONITORINFO mi;
-
-	// Grab information about our monitors
-	// For multi-monitor support, we use this instead of SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
-	hMonitor = MonitorFromWindow(pWnd->m_hWnd, MONITOR_DEFAULTTONEAREST);
-	mi.cbSize = sizeof(mi);
-	GetMonitorInfo(hMonitor, &mi);
-	rect = mi.rcWork;
-
-	bool edgeMove = true;
-	bool captionMove = false;
-
-	if (m_buttonDownOnCaption)
-	{
-		edgeMove = false;
-		captionMove = true;
-	}
-
-	// Snap to left
-	if (lpwndpos->x >= (rect.left - threshold) &&
-		lpwndpos->x <= (rect.left + threshold))
-	{
-		if (edgeMove)
-		{
-			int diff = lpwndpos->x - rect.left;
-			lpwndpos->cx += diff;
-		}
-		if (edgeMove || captionMove)
-		{
-			lpwndpos->x = rect.left;
-		}
-	}
-
-	// Snap to right
-	if ((lpwndpos->x + lpwndpos->cx) >= (rect.right - threshold) &&
-		(lpwndpos->x + lpwndpos->cx) <= (rect.right + threshold))
-	{
-		if (edgeMove)
-		{
-			int diff = rect.right - (lpwndpos->x + lpwndpos->cx);
-			lpwndpos->cx += diff;
-		}
-		if (captionMove)
-		{
-			lpwndpos->x = (rect.right - lpwndpos->cx);
-		}
-	}
-
-	// Snap to top
-	if (lpwndpos->y >= (rect.top - threshold) &&
-		lpwndpos->y <= (rect.top + threshold))
-	{
-		if (edgeMove)
-		{
-			int diff = lpwndpos->y - rect.top;
-			lpwndpos->cy += diff;
-		}
-		if (edgeMove || captionMove)
-		{
-			lpwndpos->y = rect.top;
-		}
-	}
-
-	// Snap to bottom
-	if ((lpwndpos->y + lpwndpos->cy) >= (rect.bottom - threshold) &&
-		(lpwndpos->y + lpwndpos->cy) <= (rect.bottom + threshold))
-	{
-		if (edgeMove)
-		{
-			int diff = rect.bottom - (lpwndpos->y + lpwndpos->cy);
-			lpwndpos->cy += diff;
-		}
-		if (captionMove)
-		{
-			lpwndpos->y = (rect.bottom - lpwndpos->cy);
-		}
-	}
-}
-
 void CDittoWindow::MinMaxWindow(CWnd *pWnd, long lOption)
 {
 	if ((m_bMinimized) && (lOption == FORCE_MIN))
@@ -914,7 +779,7 @@ void CDittoWindow::MinMaxWindow(CWnd *pWnd, long lOption)
 	if ((m_bMinimized == false) && (lOption == FORCE_MAX))
 		return;
 
-	if (m_lRightBorder == m_captionBorderWidth)
+	if (m_captionPosition == CAPTION_RIGHT)
 	{
 		if (m_bMinimized == false)
 		{
@@ -938,7 +803,7 @@ void CDittoWindow::MinMaxWindow(CWnd *pWnd, long lOption)
 			::SetForegroundWindow(pWnd->GetSafeHwnd());
 		}
 	}
-	if (m_lLeftBorder == m_captionBorderWidth)
+	if (m_captionPosition == CAPTION_LEFT)
 	{
 		if (m_bMinimized == false)
 		{
@@ -962,7 +827,7 @@ void CDittoWindow::MinMaxWindow(CWnd *pWnd, long lOption)
 			::SetForegroundWindow(pWnd->GetSafeHwnd());
 		}
 	}
-	else if (m_lTopBorder == m_captionBorderWidth)
+	if (m_captionPosition == CAPTION_TOP)
 	{
 		if (m_bMinimized == false)
 		{
@@ -987,7 +852,7 @@ void CDittoWindow::MinMaxWindow(CWnd *pWnd, long lOption)
 			::SetForegroundWindow(pWnd->GetSafeHwnd());
 		}
 	}
-	else if (m_lBottomBorder == m_captionBorderWidth)
+	if (m_captionPosition == CAPTION_BOTTOM)
 	{
 		if (m_bMinimized == false)
 		{
@@ -1013,4 +878,47 @@ void CDittoWindow::MinMaxWindow(CWnd *pWnd, long lOption)
 			::SetForegroundWindow(pWnd->GetSafeHwnd());
 		}
 	}
+}
+
+void CDittoWindow::OnDpiChanged(CWnd *pParent, int dpi)
+{
+	m_dpi.Update(dpi);
+
+	m_captionBorderWidth = m_dpi.ScaleX(25);
+	m_borderSize = m_dpi.ScaleX(2);
+
+	m_VertFont.Detach();
+	m_HorFont.Detach();
+
+	m_VertFont.CreateFont(m_dpi.PointsToPixels(18), 0, -900, 0, 400, FALSE, FALSE, 0, DEFAULT_CHARSET,
+		OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
+		DEFAULT_PITCH | FF_SWISS, _T("Segoe UI"));
+
+	m_HorFont.CreateFont(m_dpi.PointsToPixels(18), 0, 0, 0, 500, FALSE, FALSE, 0, DEFAULT_CHARSET,
+		OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
+		DEFAULT_PITCH | FF_SWISS, _T("Segoe UI"));
+
+	m_closeButton.Reset();
+	m_closeButton.LoadStdImageDPI(m_dpi.GetDPIX(), Close_Black_16_16, Close_Black_20_20, Close_Black_24_24, Close_Black_28, Close_Black_32_32, _T("PNG"));
+
+	m_chevronRightButton.Reset();
+	m_chevronRightButton.LoadStdImageDPI(m_dpi.GetDPIX(), ChevronRight_Black_16_16, ChevronRight_Black_20_20, ChevronRight_Black_24_24, ChevronRight_Black_28, ChevronRight_Black_32_32, _T("PNG"));
+	
+	m_chevronLeftButton.Reset();
+	m_chevronLeftButton.LoadStdImageDPI(m_dpi.GetDPIX(), ChevronLeft_Black_16_16, ChevronLeft_Black_20_20, ChevronLeft_Black_24_24, ChevronLeft_Black_28, ChevronLeft_Black_32_32, _T("PNG"));
+
+	m_maximizeButton.Reset();
+	m_maximizeButton.LoadStdImageDPI(m_dpi.GetDPIX(), IDB_MAXIMIZE_16_16, maximize_20, maximize_24, maximize_28, maximize_32, _T("PNG"));
+
+	m_minimizeButton.Reset();
+	m_minimizeButton.LoadStdImageDPI(m_dpi.GetDPIX(), minimize_16, minimize_20, minimize_24, minimize_28, minimize_32, _T("PNG"));
+
+	SetTitleTextHeight(pParent);
+
+	/*pParent->SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
+
+	pParent->Invalidate();
+	pParent->RedrawWindow();*/
+
+	//::SetWindowPos(pParent->m_hWnd, NULL, 0, 0, 0, 0, SWP_DRAWFRAME | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
 }

+ 10 - 12
DittoWindow.h

@@ -1,8 +1,8 @@
 #pragma once
 
 #include "GdipButton.h"
-
 #include "GdiImageDrawer.h"
+#include "DPI.h"
 
 #define BUTTON_CLOSE 1
 #define BUTTON_CHEVRON 2
@@ -25,7 +25,6 @@ public:
 	void DoCreate(CWnd *pWnd);
 	void DoNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp);
 	UINT DoNcHitTest(CWnd *pWnd, CPoint point);
-	void DoSetRegion(CWnd *pWnd);
 	long DoNcLButtonUp(CWnd *pWnd, UINT nHitTest, CPoint point);
 	int DoNcLButtonDown(CWnd *pWnd, UINT nHitTest, CPoint point);
 	void DoNcMouseMove(CWnd *pWnd, UINT nHitTest, CPoint point) ;
@@ -33,18 +32,11 @@ public:
 	void SetCaptionOn(CWnd *pWnd, int nPos, bool bOnstartup, int captionSize, int captionFontSize);
 	bool SetCaptionColors(COLORREF left, COLORREF right, COLORREF border);
 	void SetCaptionTextColor(COLORREF color);
-
 	void MinMaxWindow(CWnd *pWnd, long lOption);
-
 	void SetTitleTextHeight(CWnd *pWnd);
-
-	void SnapToEdge(CWnd *pWnd, WINDOWPOS* lpwndpos);
-
-	long m_lTopBorder;
-	long m_lRightBorder;
-	long m_lBottomBorder;
-	long m_lLeftBorder;
-
+	int IndexToPos(int index, bool horizontal);
+	void OnDpiChanged(CWnd *pWnd, int dpi);
+	
 	bool m_bDrawClose;
 	bool m_sendWMClose;
 	bool m_bDrawChevron;
@@ -88,6 +80,9 @@ public:
 
 	int m_captionBorderWidth;
 
+	int m_captionPosition;
+	int m_borderSize;
+
 	int m_titleTextHeight;
 
 	bool m_buttonDownOnCaption;
@@ -95,4 +90,7 @@ public:
 	CRect m_crFullSizeWindow;
 	COleDateTime m_TimeMinimized;
 	COleDateTime m_TimeMaximized;
+
+
+	CDPI m_dpi;
 };

+ 36 - 5
EditFrameWnd.cpp

@@ -42,6 +42,9 @@ BEGIN_MESSAGE_MAP(CEditFrameWnd, CFrameWnd)
 	ON_WM_NCLBUTTONDBLCLK()
 	ON_WM_WINDOWPOSCHANGING()
 	ON_WM_TIMER()
+	ON_MESSAGE(WM_DPICHANGED, OnDpiChanged)
+	ON_WM_MOVING()
+	ON_WM_ENTERSIZEMOVE()
 END_MESSAGE_MAP()
 
 
@@ -88,9 +91,6 @@ void CEditFrameWnd::OnDestroy()
 void CEditFrameWnd::OnSize(UINT nType, int cx, int cy)
 {
 	CFrameWnd::OnSize(nType, cx, cy);
-
-	m_DittoWindow.DoSetRegion(this);
-
 	MoveControls();
 }
 
@@ -108,6 +108,7 @@ bool CEditFrameWnd::EditIds(CClipIDs &Ids)
 {
 	return m_EditWnd.EditIds(Ids);
 }
+
 BOOL CEditFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
 {
 	if(cs.hMenu!=NULL)  
@@ -235,8 +236,6 @@ void CEditFrameWnd::OnNcLButtonDblClk(UINT nHitTest, CPoint point)
 void CEditFrameWnd::OnWindowPosChanging(WINDOWPOS* lpwndpos)
 {
 	CFrameWnd::OnWindowPosChanging(lpwndpos);
-
-	m_DittoWindow.SnapToEdge(this, lpwndpos);
 }
 
 void CEditFrameWnd::OnTimer(UINT_PTR nIDEvent)
@@ -255,4 +254,36 @@ void CEditFrameWnd::OnTimer(UINT_PTR nIDEvent)
 	}
 
 	CWnd::OnTimer(nIDEvent);
+}
+
+LRESULT CEditFrameWnd::OnDpiChanged(WPARAM wParam, LPARAM lParam)
+{
+	int dpi = HIWORD(wParam);
+	m_DittoWindow.OnDpiChanged(this, dpi);
+
+	RECT* const prcNewWindow = (RECT*)lParam;
+	SetWindowPos(NULL,
+		prcNewWindow->left,
+		prcNewWindow->top,
+		prcNewWindow->right - prcNewWindow->left,
+		prcNewWindow->bottom - prcNewWindow->top,
+		SWP_NOZORDER | SWP_NOACTIVATE);
+
+
+	this->Invalidate();
+	this->UpdateWindow();
+
+	return TRUE;
+}
+
+void CEditFrameWnd::OnMoving(UINT fwSide, LPRECT pRect)
+{
+	CWnd::OnMoving(fwSide, pRect);
+	m_snap.OnSnapMoving(m_hWnd, pRect);
+}
+
+void CEditFrameWnd::OnEnterSizeMove()
+{
+	m_snap.OnSnapEnterSizeMove(m_hWnd);
+	CWnd::OnEnterSizeMove();
 }

+ 6 - 1
EditFrameWnd.h

@@ -2,8 +2,8 @@
 
 #include "EditWnd.h"
 #include "ClipIds.h"
-
 #include "DittoWindow.h"
+#include "SnapWindow.h"
 
 class CEditFrameWnd : public CFrameWnd
 {
@@ -21,6 +21,7 @@ protected:
 	HWND m_hNotifyWnd;
 	CDittoWindow m_DittoWindow;
 	CRect m_crIcon;
+	SnapWindow m_snap;
 
 protected:
 	DECLARE_MESSAGE_MAP()
@@ -47,6 +48,10 @@ public:
 	afx_msg void OnNcLButtonDblClk(UINT nHitTest, CPoint point);
 	afx_msg void OnWindowPosChanging(WINDOWPOS* lpwndpos);
 	afx_msg void OnTimer(UINT_PTR nIDEvent);
+	afx_msg LRESULT OnDpiChanged(WPARAM wParam, LPARAM lParam);
+	afx_msg void OnMoving(UINT fwSide, LPRECT pRect);
+	afx_msg void OnEnterSizeMove();
 };
 
 
+

+ 17 - 13
GdiImageDrawer.cpp

@@ -13,6 +13,13 @@ CGdiImageDrawer::~CGdiImageDrawer()
 	delete m_pStdImage;
 }
 
+void CGdiImageDrawer::Reset()
+{
+	delete m_pStdImage;
+	m_pStdImage = NULL;
+
+}
+
 BOOL CGdiImageDrawer::LoadStdImage(UINT id, LPCTSTR pType)
 {
 	m_pStdImage = new CGdiPlusBitmapResource;
@@ -25,23 +32,23 @@ BOOL CGdiImageDrawer::LoadRaw(unsigned char* bitmapData, int imageSize)
 	return m_pStdImage->LoadRaw(bitmapData, imageSize);
 }
 
-BOOL CGdiImageDrawer::LoadStdImageDPI(UINT id96, UINT id120, UINT id144, UINT id168, UINT id192, LPCTSTR pType)
+BOOL CGdiImageDrawer::LoadStdImageDPI(int dpi, UINT id96, UINT id120, UINT id144, UINT id168, UINT id192, LPCTSTR pType)
 {
 	BOOL ret = FALSE;
 
-	if (theApp.m_metrics.GetDPIX() >= 192)
+	if (dpi >= 192)
 	{
 		ret = LoadStdImage(id192, pType);
 	}
-	else if (theApp.m_metrics.GetDPIX() >= 168)
+	else if (dpi >= 168)
 	{
 		ret = LoadStdImage(id168, pType);
 	}
-	else if (theApp.m_metrics.GetDPIX() >= 144)
+	else if (dpi >= 144)
 	{
 		ret = LoadStdImage(id144, pType);
 	}
-	else if (theApp.m_metrics.GetDPIX() >= 120)
+	else if (dpi >= 120)
 	{
 		ret = LoadStdImage(id120, pType);
 	}
@@ -53,7 +60,7 @@ BOOL CGdiImageDrawer::LoadStdImageDPI(UINT id96, UINT id120, UINT id144, UINT id
 	return ret;
 }
 
-void CGdiImageDrawer::Draw(CDC* pScreenDC, CWnd *pWnd, CRect rc, bool mouseHover, bool mouseDown)
+void CGdiImageDrawer::Draw(CDC* pScreenDC, CDPI &dpi, CWnd *pWnd, CRect rc, bool mouseHover, bool mouseDown)
 {
 	int width = m_pStdImage->m_pBitmap->GetWidth();
 	int height = m_pStdImage->m_pBitmap->GetHeight();
@@ -61,10 +68,10 @@ void CGdiImageDrawer::Draw(CDC* pScreenDC, CWnd *pWnd, CRect rc, bool mouseHover
 	int x = rc.left + (rc.Width() / 2) - (width / 2);
 	int y = rc.top + (rc.Height() / 2) - (height / 2);
 
-	Draw(pScreenDC, pWnd, x, y, mouseHover, mouseDown);
+	Draw(pScreenDC, dpi, pWnd, x, y, mouseHover, mouseDown);
 }
 
-void CGdiImageDrawer::Draw(CDC* pScreenDC, CWnd *pWnd, int posX, int posY, bool mouseHover, bool mouseDown, int forceWidth, int forceHeight)
+void CGdiImageDrawer::Draw(CDC* pScreenDC, CDPI &dpi, CWnd *pWnd, int posX, int posY, bool mouseHover, bool mouseDown, int forceWidth, int forceHeight)
 {
 	int width = m_pStdImage->m_pBitmap->GetWidth();
 	if (forceWidth != INT_MAX)
@@ -74,10 +81,7 @@ void CGdiImageDrawer::Draw(CDC* pScreenDC, CWnd *pWnd, int posX, int posY, bool
 		height = forceHeight;
 
 	CRect rectWithBorder(posX, posY, posX + width, posY + height);
-
-	//int two = theApp.m_metrics.ScaleX(2);
-	//rectWithBorder.InflateRect(two, two, two, two);
-
+	
 	CDC dcBk;
 	CBitmap bmp;
 	CClientDC clDC(pWnd);
@@ -93,7 +97,7 @@ void CGdiImageDrawer::Draw(CDC* pScreenDC, CWnd *pWnd, int posX, int posY, bool
 	//Draw the png file
 	if (mouseDown)
 	{
-		int one = theApp.m_metrics.ScaleX(1);
+		int one = dpi.ScaleX(1);
 		posX += one;
 		posY += one;
 	}

+ 8 - 5
GdiImageDrawer.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include "CGdiPlusBitmap.h"
+#include "DPI.h"
 
 class CGdiImageDrawer
 {
@@ -9,18 +10,20 @@ public:
 	~CGdiImageDrawer();
 
 	BOOL LoadStdImage(UINT id, LPCTSTR pType);
-	BOOL LoadStdImageDPI(UINT id96, UINT id120, UINT id144, UINT id168, UINT id192, LPCTSTR pType);
-	void Draw(CDC* pScreenDC, CWnd *pWnd, int posX, int posY, bool mouseHover, bool mouseDown, int forceWidth = INT_MAX, int forceHeight = INT_MAX);
-	void Draw(CDC* pScreenDC, CWnd *pWnd, CRect rc, bool mouseHover, bool mouseDown);
+	BOOL LoadStdImageDPI(int dpi, UINT id96, UINT id120, UINT id144, UINT id168, UINT id192, LPCTSTR pType);
+	void Draw(CDC* pScreenDC, CDPI &dpi, CWnd *pWnd, int posX, int posY, bool mouseHover, bool mouseDown, int forceWidth = INT_MAX, int forceHeight = INT_MAX);
+	void Draw(CDC* pScreenDC, CDPI &dpi, CWnd *pWnd, CRect rc, bool mouseHover, bool mouseDown);
 	BOOL LoadRaw(unsigned char* bitmapData, int imageSize);
 
 	UINT ImageWidth() { return m_pStdImage->m_pBitmap->GetWidth(); }
 	UINT ImageHeight() { return m_pStdImage->m_pBitmap->GetHeight(); }
 
+	void Reset();
+
 protected:
 	CGdiPlusBitmapResource* m_pStdImage;
-	CDC*	m_pCurBtn;		// current pointer to one of the above
-	CDC		m_dcStd;		// standard button
+	//CDC*	m_pCurBtn;		// current pointer to one of the above
+	//CDC		m_dcStd;		// standard button
 
 	//CDC m_dcBk;
 };

+ 12 - 8
GdipButton.cpp

@@ -82,23 +82,23 @@ BEGIN_MESSAGE_MAP(CGdipButton, CButton)
 END_MESSAGE_MAP()
 
 
-BOOL CGdipButton::LoadStdImageDPI(UINT id96, UINT id120, UINT id144, UINT id168, UINT id192, LPCTSTR pType)
+BOOL CGdipButton::LoadStdImageDPI(int dpiX, UINT id96, UINT id120, UINT id144, UINT id168, UINT id192, LPCTSTR pType)
 {
 	BOOL ret = FALSE;
 
-	if (theApp.m_metrics.GetDPIX() >= 192)
+	if (dpiX >= 192)
 	{
 		ret = LoadStdImage(id192, pType);
 	}
-	else if (theApp.m_metrics.GetDPIX() >= 168)
+	else if (dpiX >= 168)
 	{
 		ret = LoadStdImage(id168, pType);
 	}
-	else if (theApp.m_metrics.GetDPIX() >= 144)
+	else if (dpiX >= 144)
 	{
 		ret = LoadStdImage(id144, pType);
 	}
-	else if (theApp.m_metrics.GetDPIX() >= 120)
+	else if (dpiX >= 120)
 	{
 		ret = LoadStdImage(id120, pType);
 	}
@@ -138,9 +138,13 @@ BOOL CGdipButton::LoadStdImage(UINT id, LPCTSTR pType)
 
 void CGdipButton::Reset()
 {
-	/*if(m_pStdImage) delete m_pStdImage;
-	if (m_pAltImage) delete m_pAltImage;
-	if (m_pToolTip)	delete m_pToolTip;*/
+	delete m_pStdImage;
+	m_pStdImage = NULL;
+	delete m_pAltImage;
+	m_pAltImage = NULL;
+	delete m_pToolTip;
+	m_pToolTip = NULL;
+
 	m_bHaveBitmaps = FALSE;
 	m_bHaveAltImage = FALSE;
 

+ 1 - 1
GdipButton.h

@@ -54,7 +54,7 @@ public:
 	BOOL LoadAltImage(UINT id, LPCTSTR pType);
 	BOOL LoadStdImage(UINT id, LPCTSTR pType);
 
-	BOOL LoadStdImageDPI(UINT id96, UINT id120, UINT id144, UINT id168, UINT id192, LPCTSTR pType);
+	BOOL LoadStdImageDPI(int dpiX, UINT id96, UINT id120, UINT id144, UINT id168, UINT id192, LPCTSTR pType);
 
 	// if false, disables the press state and uses grayscale image if it exists
 	void EnableButton(BOOL bEnable = TRUE) { m_bIsDisabled = !bEnable; }

+ 0 - 13
MainFrm.cpp

@@ -1331,19 +1331,6 @@ LRESULT CMainFrame::OnShowMsgWindow(WPARAM wParam, LPARAM lParam)
 	CString *pMsg = (CString*)wParam;
 	int clipId = (int)lParam;
 
-	/*CRect r;
-	GetMonitorRect(0, r);
-
-	m_pPopupWindow = new CDittoPopupWindow();
-	m_pPopupWindow->Create(CRect(r.right - 400, r.bottom - 100, r.right - 10, r.bottom - 10), this);		
-	::SetWindowPos(m_pPopupWindow->m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
-	m_pPopupWindow->SetWindowText(_T("Saved clip to group"));
-	m_pPopupWindow->ShowWindow(SW_SHOW);
-	m_pPopupWindow->SetCopyToGroupId(clipId);
-	m_pPopupWindow->UpdateText(*pMsg);	
-
-	SetTimer(CLOSE_POPUP_MSG_WND, 2500, 0);*/
-
 	m_trayIcon.SetBalloonDetails(pMsg->GetBuffer(), _T("Ditto"), CTrayNotifyIcon::BalloonStyle::Info, CGetSetOptions::GetBalloonTimeout());
 
 	delete pMsg;

+ 1 - 1
Options.cpp

@@ -1419,7 +1419,7 @@ BOOL CGetSetOptions::GetFont(LOGFONT &font)
 	}
 
 	ZeroMemory(&font, sizeof(font));
-	font.lfHeight = -theApp.m_metrics.PointsToPixels(10);
+	font.lfHeight = -10;
 	font.lfWeight = 400;
 	font.lfCharSet = 1;
 	STRCPY(font.lfFaceName, _T("Segoe UI"));

+ 26 - 4
OptionsGeneral.cpp

@@ -132,7 +132,7 @@ BOOL COptionsGeneral::OnInitDialog()
 	}
 
 	CString cs;
-	cs.Format(_T("Font - %s (%d)"), m_LogFont.lfFaceName, abs(theApp.m_metrics.PixelsToPoints(m_LogFont.lfHeight)));
+	cs.Format(_T("Font - %s (%d)"), m_LogFont.lfFaceName, GetFontSize(m_hWnd, m_LogFont));
 	m_btFont.SetWindowText(cs);
 
 	FillThemes();
@@ -541,7 +541,7 @@ void COptionsGeneral::OnBnClickedButtonDefaultFault()
 
 	memset(&m_LogFont, 0, sizeof(m_LogFont));
 
-	m_LogFont.lfHeight = -theApp.m_metrics.PointsToPixels(10);
+	m_LogFont.lfHeight = -10;
 	m_LogFont.lfWeight = 400;
 	m_LogFont.lfCharSet = 1;
 	STRCPY(m_LogFont.lfFaceName, _T("Segoe UI"));
@@ -552,12 +552,34 @@ void COptionsGeneral::OnBnClickedButtonDefaultFault()
 	m_btFont.SetFont(&m_Font);
 
 	CString cs;
-	cs.Format(_T("Font - %s (%d)"), m_LogFont.lfFaceName, abs(theApp.m_metrics.PixelsToPoints(m_LogFont.lfHeight)));
+	cs.Format(_T("Font - %s (%d)"), m_LogFont.lfFaceName, GetFontSize(m_hWnd, m_LogFont));
 	m_btFont.SetWindowText(cs);
 
 	this->SetFont(&m_Font);
 }
 
+int COptionsGeneral::GetFontSize(HWND hWnd, const LOGFONT& lf)
+{
+	int nFontSize = 0;
+
+	HDC hDC = ::GetWindowDC(hWnd);
+
+	if (lf.lfHeight < 0)
+	{
+		nFontSize = -::MulDiv(lf.lfHeight, 72, ::GetDeviceCaps(hDC, LOGPIXELSY));
+	}
+	else
+	{
+		TEXTMETRIC tm;
+		::ZeroMemory(&tm, sizeof(TEXTMETRIC));
+		::GetTextMetrics(hDC, &tm);
+
+		nFontSize = ::MulDiv(lf.lfHeight - tm.tmInternalLeading, 72, ::GetDeviceCaps(hDC, LOGPIXELSY));
+	}
+	::ReleaseDC(hWnd, hDC);
+
+	return nFontSize;
+}
 
 void COptionsGeneral::OnBnClickedButtonFont()
 {
@@ -573,7 +595,7 @@ void COptionsGeneral::OnBnClickedButtonFont()
 		m_btFont.SetFont(&m_Font);
 
 		CString cs;
-		cs.Format(_T("Font - %s (%d)"), m_LogFont.lfFaceName, abs(theApp.m_metrics.PixelsToPoints(m_LogFont.lfHeight)));
+		cs.Format(_T("Font - %s (%d)"), m_LogFont.lfFaceName, GetFontSize(m_hWnd, m_LogFont));
 		m_btFont.SetWindowText(cs);
 	}
 }

+ 2 - 6
OptionsGeneral.h

@@ -66,19 +66,15 @@ public:
 protected:
 	
 	COptionsSheet *m_pParent;
-
 	CString m_csTitle;
-
 	CBrush m_brush;
-
 	CFont m_Font;
 	LOGFONT m_LogFont;
-
 	CFont m_envVarFont;
-
-	void FillThemes();
 	
+	void FillThemes();	
 	void FillLanguages();
+	int GetFontSize(HWND hWnd, const LOGFONT& lf);
 
 	// Generated message map functions
 	//{{AFX_MSG(COptionsGeneral)

+ 1 - 1
OptionsQuickPaste.cpp

@@ -231,7 +231,7 @@ void COptionsQuickPaste::OnButtonDefaultFault()
 
 	memset(&m_LogFont, 0, sizeof(m_LogFont));
 
-	m_LogFont.lfHeight = -theApp.m_metrics.PointsToPixels(10);
+	m_LogFont.lfHeight = -10;
 	m_LogFont.lfWeight = 400;
 	m_LogFont.lfCharSet = 1;
 	STRCPY(m_LogFont.lfFaceName, _T("Segoe UI"));

+ 82 - 57
QListCtrl.cpp

@@ -37,43 +37,16 @@ CQListCtrl::CQListCtrl()
 	m_pchTip = NULL;
 	m_pwchTip = NULL;
 	m_linesPerRow = 1;
-	
-	LOGFONT lf;
-	
-	lf.lfHeight = theApp.m_metrics.PointsToPixels(-7);
-	lf.lfWidth = 0;
-	lf.lfEscapement = 0;
-	lf.lfOrientation = 0;
-	lf.lfWeight = FW_LIGHT;
-	lf.lfItalic = FALSE;
-	lf.lfUnderline = FALSE;
-	lf.lfStrikeOut = FALSE;
-	lf.lfCharSet = ANSI_CHARSET;
-	lf.lfOutPrecision = OUT_STRING_PRECIS;
-	lf.lfClipPrecision = CLIP_STROKE_PRECIS;
-	lf.lfQuality = DEFAULT_QUALITY;
-	lf.lfPitchAndFamily = VARIABLE_PITCH | FF_DONTCARE;
-	lstrcpy(lf.lfFaceName, _T("Small Font"));
-	
-	m_SmallFont = ::CreateFontIndirect(&lf);
-		
+	m_windowDpi = NULL;
+	m_SmallFont = NULL;		
 	m_bStartTop = true;
 	m_pToolTip = NULL;
 	m_pFormatter = NULL;
 	m_allSelected = false;
 	m_rowHeight = 50;
-
 	m_mouseOverScrollAreaStart = 0;
-
-	m_groupFolder.LoadStdImageDPI(IDB_OPEN_FOLDER_16_16, IDB_OPEN_FOLDER_20_20, IDB_OPEN_FOLDER_24_24, IDB_OPEN_FOLDER_24_24, IDB_OPEN_FOLDER_32_32, _T("PNG"));
-	m_dontDeleteImage.LoadStdImageDPI(IDB_YELLOW_STAR_16_16, IDB_YELLOW_STAR_20_20, IDB_YELLOW_STAR_24_24, IDB_YELLOW_STAR_24_24, IDB_YELLOW_STAR_32_32, _T("PNG"));
-	m_inFolderImage.LoadStdImageDPI(IDB_IN_FOLDER_16_16, IDB_IN_FOLDER_20_20, IDB_IN_FOLDER_24_24, IDB_IN_FOLDER_24_24, IDB_IN_FOLDER_32_32, _T("PNG"));
-	m_shortCutImage.LoadStdImageDPI(IDB_KEY_16_16, IDB_KEY_20_20, IDB_KEY_24_24, IDB_KEY_24_24, IDB_KEY_32_32, _T("PNG"));
-	m_stickyImage.LoadStdImageDPI(IDB_STICKY_16_16, IDB_STICKY_20_20, IDB_STICKY_24_24, IDB_STICKY_24_24, IDB_STICKY_32_32, _T("PNG"));
-
 	m_showIfClipWasPasted = TRUE;
 	m_bShowTextForFirstTenHotKeys = true;
-
 	m_pToolTipActions = NULL;
 }
 
@@ -97,6 +70,8 @@ CQListCtrl::~CQListCtrl()
 		delete m_pFormatter;
 		m_pFormatter = NULL;
 	}
+
+	DeleteObject(m_SmallFont);
 }
 
 // returns the position 1-10 if the index is in the FirstTen block else -1
@@ -274,9 +249,10 @@ BOOL CQListCtrl::SetFormattedText(int nRow, int nCol, LPCTSTR lpszFormat,...)
 	return SetText(nRow,nCol,csText);
 }
 
-void CQListCtrl::SetNumberOfLinesPerRow(int nLines)
+void CQListCtrl::SetNumberOfLinesPerRow(int nLines, bool force)
 {
-	if(m_linesPerRow != nLines)
+	if(m_linesPerRow != nLines ||
+		force)
 	{
 		m_linesPerRow = nLines;
 
@@ -298,8 +274,11 @@ void CQListCtrl::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
 	CFont* pFont = GetFont();
 	HFONT hFontOld = (HFONT)SelectObject(hDC, pFont->GetSafeHandle());
 	GetTextMetrics(hDC, &tm);
-	lpMeasureItemStruct->itemHeight = ((tm.tmHeight + tm.tmExternalLeading) * m_linesPerRow) + ROW_BOTTOM_BORDER;
-	m_rowHeight = lpMeasureItemStruct->itemHeight;
+	if (m_windowDpi != NULL)
+	{
+		lpMeasureItemStruct->itemHeight = ((tm.tmHeight + tm.tmExternalLeading) * m_linesPerRow) + m_windowDpi->ScaleX(ROW_BOTTOM_BORDER);
+		m_rowHeight = lpMeasureItemStruct->itemHeight;
+	}
 	SelectObject(hDC, hFontOld);
 	::ReleaseDC(NULL, hDC);
 }
@@ -398,11 +377,11 @@ void CQListCtrl::OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult)
 		{
 			CRect pastedRect(rcItem);
 			pastedRect.left++;
-			pastedRect.right = rcItem.left + theApp.m_metrics.ScaleX(3);
+			pastedRect.right = rcItem.left + m_windowDpi->ScaleX(3);
 				
 			pDC->FillSolidRect(pastedRect, g_Opt.m_Theme.ClipPastedColor());
 
-			rcText.left += theApp.m_metrics.ScaleX(4);
+			rcText.left += m_windowDpi->ScaleX(4);
 		}
 		        		
 		// set firstTenNum to the first ten number (1-10) corresponding to
@@ -412,7 +391,7 @@ void CQListCtrl::OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult)
 		
 		if( m_bShowTextForFirstTenHotKeys && firstTenNum > 0 )
 		{
-			rcText.left += theApp.m_metrics.ScaleX(12);
+			rcText.left += m_windowDpi->ScaleX(12);
 		}
 		
 		bool drawInGroupIcon = true;
@@ -431,32 +410,32 @@ void CQListCtrl::OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult)
 		{
 			if(strSymbols.Find(_T("<group>")) >= 0) //group 
 			{
-				m_groupFolder.Draw(pDC, this, rcText.left, rcText.top, false, false);
-				rcText.left += m_groupFolder.ImageWidth() + theApp.m_metrics.ScaleX(2);
+				m_groupFolder.Draw(pDC, *m_windowDpi, this, rcText.left, rcText.top, false, false);
+				rcText.left += m_groupFolder.ImageWidth() + m_windowDpi->ScaleX(2);
 			}
 			if (strSymbols.Find(_T("<noautodelete>")) >= 0) //don't auto delete
 			{
-				m_dontDeleteImage.Draw(pDC, this, rcText.left, rcText.top, false, false);
-				rcText.left += m_dontDeleteImage.ImageWidth() + theApp.m_metrics.ScaleX(2);
+				m_dontDeleteImage.Draw(pDC, *m_windowDpi, this, rcText.left, rcText.top, false, false);
+				rcText.left += m_dontDeleteImage.ImageWidth() + m_windowDpi->ScaleX(2);
 			}
 			if (strSymbols.Find(_T("<shortcut>")) >= 0) // has shortcut
 			{
-				m_shortCutImage.Draw(pDC, this, rcText.left, rcText.top, false, false);
-				rcText.left += m_shortCutImage.ImageWidth() + theApp.m_metrics.ScaleX(2);
+				m_shortCutImage.Draw(pDC, *m_windowDpi, this, rcText.left, rcText.top, false, false);
+				rcText.left += m_shortCutImage.ImageWidth() + m_windowDpi->ScaleX(2);
 			}
 			if (drawInGroupIcon &&
 				strSymbols.Find(_T("<ingroup>")) >= 0) // in group
 			{
-				m_inFolderImage.Draw(pDC, this, rcText.left, rcText.top, false, false);
-				rcText.left += m_inFolderImage.ImageWidth() + theApp.m_metrics.ScaleX(2);
+				m_inFolderImage.Draw(pDC, *m_windowDpi, this, rcText.left, rcText.top, false, false);
+				rcText.left += m_inFolderImage.ImageWidth() + m_windowDpi->ScaleX(2);
 			}
 			if (strSymbols.Find(_T("<qpastetext>")) >= 0) // has quick paste text
 			{
 			}
 			if (strSymbols.Find(_T("<sticky>")) >= 0) //sticky clip
 			{
-				m_stickyImage.Draw(pDC, this, rcText.left, rcText.top, false, false);
-				rcText.left += m_stickyImage.ImageWidth() + theApp.m_metrics.ScaleX(2);
+				m_stickyImage.Draw(pDC, *m_windowDpi, this, rcText.left, rcText.top, false, false);
+				rcText.left += m_stickyImage.ImageWidth() + m_windowDpi->ScaleX(2);
 			}			
 		}
 		
@@ -497,9 +476,9 @@ void CQListCtrl::OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult)
 			if (m_showIfClipWasPasted)
 				extraFromClipWasPaste = 3;
 			
-			crHotKey.right = crHotKey.left + theApp.m_metrics.ScaleX(11);
-			crHotKey.left += theApp.m_metrics.ScaleX(1 + extraFromClipWasPaste);
-			crHotKey.top += theApp.m_metrics.ScaleX(1 + extraFromClipWasPaste);
+			crHotKey.right = crHotKey.left + m_windowDpi->ScaleX(11);
+			crHotKey.left += m_windowDpi->ScaleX(1 + extraFromClipWasPaste);
+			crHotKey.top += m_windowDpi->ScaleX(1 + extraFromClipWasPaste);
 			
 			HFONT hOldFont = (HFONT)pDC->SelectObject(m_SmallFont);
 			COLORREF localOldTextColor = pDC->SetTextColor(g_Opt.m_Theme.ListSmallQuickPasteIndexColor());
@@ -509,8 +488,8 @@ void CQListCtrl::OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult)
 						
 			pDC->DrawText(cs, crHotKey, DT_BOTTOM);
 			
-			pDC->MoveTo(CPoint(rcItem.left + theApp.m_metrics.ScaleX(8 + extraFromClipWasPaste), rcItem.top));
-			pDC->LineTo(CPoint(rcItem.left + theApp.m_metrics.ScaleX(8 + extraFromClipWasPaste), rcItem.bottom));
+			pDC->MoveTo(CPoint(rcItem.left + m_windowDpi->ScaleX(8 + extraFromClipWasPaste), rcItem.top));
+			pDC->LineTo(CPoint(rcItem.left + m_windowDpi->ScaleX(8 + extraFromClipWasPaste), rcItem.bottom));
 			
 			pDC->SelectObject(hOldFont);
 			pDC->SetTextColor(localOldTextColor);
@@ -1437,8 +1416,8 @@ void CQListCtrl::OnTimer(UINT_PTR nIDEvent)
 				this->GetWindowRect(&crWindow);
 
 				//Adjust for the v-scroll bar being off of the screen
-				crWindow.right -= theApp.m_metrics.ScaleX(GetSystemMetrics(SM_CXVSCROLL));
-				crWindow.bottom -= theApp.m_metrics.ScaleX(::GetSystemMetrics(SM_CXHSCROLL));
+				crWindow.right -= m_windowDpi->ScaleX(GetSystemMetrics(SM_CXVSCROLL));
+				crWindow.bottom -= m_windowDpi->ScaleX(::GetSystemMetrics(SM_CXHSCROLL));
 
 				//Check and see if we are still in the cursor area
 				if(MouseInScrollBarArea(crWindow, cursorPos))
@@ -1519,8 +1498,8 @@ void CQListCtrl::OnMouseMove(UINT nFlags, CPoint point)
 		this->GetWindowRect(&crWindow);
 		ScreenToClient(&crWindow);
 
-		crWindow.right -= theApp.m_metrics.ScaleX(::GetSystemMetrics(SM_CXVSCROLL));
-		crWindow.bottom -= theApp.m_metrics.ScaleX(::GetSystemMetrics(SM_CXHSCROLL));
+		crWindow.right -= m_windowDpi->ScaleX(::GetSystemMetrics(SM_CXVSCROLL));
+		crWindow.bottom -= m_windowDpi->ScaleX(::GetSystemMetrics(SM_CXHSCROLL));
 
 		if(MouseInScrollBarArea(crWindow, point))
 		{
@@ -1549,8 +1528,8 @@ bool CQListCtrl::MouseInScrollBarArea(CRect crWindow, CPoint point)
 	CRect crRight(crWindow);
 	CRect crBottom(crWindow);	
 
-	crRight.left = crRight.right - theApp.m_metrics.ScaleX(::GetSystemMetrics(SM_CXVSCROLL));
-	crBottom.top = crBottom.bottom - theApp.m_metrics.ScaleY(::GetSystemMetrics(SM_CYHSCROLL));
+	crRight.left = crRight.right - m_windowDpi->ScaleX(::GetSystemMetrics(SM_CXVSCROLL));
+	crBottom.top = crBottom.bottom - m_windowDpi->ScaleY(::GetSystemMetrics(SM_CYHSCROLL));
 
 	/*CString cs;
 	cs.Format(_T("point.x: %d, Width: %d, Height: %d\n"), point.x, crWindow.Width(), crWindow.Height());
@@ -1654,4 +1633,50 @@ void CQListCtrl::HideToolTip()
 	{
 		m_pToolTip->Hide();
 	}
+}
+
+void CQListCtrl::OnDpiChanged()
+{
+	SetDpiInfo(m_windowDpi);
+}
+
+void CQListCtrl::SetDpiInfo(CDPI *dpi)
+{
+	m_windowDpi = dpi;
+
+	m_groupFolder.Reset();
+	m_groupFolder.LoadStdImageDPI(m_windowDpi->GetDPIX(), IDB_OPEN_FOLDER_16_16, IDB_OPEN_FOLDER_20_20, IDB_OPEN_FOLDER_24_24, IDB_OPEN_FOLDER_24_24, IDB_OPEN_FOLDER_32_32, _T("PNG"));
+
+	m_dontDeleteImage.Reset();
+	m_dontDeleteImage.LoadStdImageDPI(m_windowDpi->GetDPIX(), IDB_YELLOW_STAR_16_16, IDB_YELLOW_STAR_20_20, IDB_YELLOW_STAR_24_24, IDB_YELLOW_STAR_24_24, IDB_YELLOW_STAR_32_32, _T("PNG"));
+
+	m_inFolderImage.Reset();
+	m_inFolderImage.LoadStdImageDPI(m_windowDpi->GetDPIX(), IDB_IN_FOLDER_16_16, IDB_IN_FOLDER_20_20, IDB_IN_FOLDER_24_24, IDB_IN_FOLDER_24_24, IDB_IN_FOLDER_32_32, _T("PNG"));
+
+	m_shortCutImage.Reset();
+	m_shortCutImage.LoadStdImageDPI(m_windowDpi->GetDPIX(), IDB_KEY_16_16, IDB_KEY_20_20, IDB_KEY_24_24, IDB_KEY_24_24, IDB_KEY_32_32, _T("PNG"));
+
+	m_stickyImage.Reset();
+	m_stickyImage.LoadStdImageDPI(m_windowDpi->GetDPIX(), IDB_STICKY_16_16, IDB_STICKY_20_20, IDB_STICKY_24_24, IDB_STICKY_24_24, IDB_STICKY_32_32, _T("PNG"));
+
+	DeleteObject(m_SmallFont);
+
+	LOGFONT lf;
+
+	lf.lfHeight = m_windowDpi->PointsToPixels(-7);
+	lf.lfWidth = 0;
+	lf.lfEscapement = 0;
+	lf.lfOrientation = 0;
+	lf.lfWeight = FW_LIGHT;
+	lf.lfItalic = FALSE;
+	lf.lfUnderline = FALSE;
+	lf.lfStrikeOut = FALSE;
+	lf.lfCharSet = ANSI_CHARSET;
+	lf.lfOutPrecision = OUT_STRING_PRECIS;
+	lf.lfClipPrecision = CLIP_STROKE_PRECIS;
+	lf.lfQuality = DEFAULT_QUALITY;
+	lf.lfPitchAndFamily = VARIABLE_PITCH | FF_DONTCARE;
+	lstrcpy(lf.lfFaceName, _T("Small Font"));
+
+	m_SmallFont = ::CreateFontIndirect(&lf);
 }

+ 10 - 2
QListCtrl.h

@@ -13,6 +13,7 @@
 #include "ClipFormatQListCtrl.h"
 #include "Accels.h"
 #include "GdiImageDrawer.h"
+#include "DPI.h"
 
 #define NM_SEARCH_ENTER_PRESSED		WM_USER+0x100
 #define NM_RIGHT					WM_USER+0x101
@@ -42,6 +43,7 @@
 #define NM_DELETE_ID				WM_USER+0x127
 #define NM_MOVE_TO_GROUP			WM_USER+0x128
 #define NM_FOCUS_ON_SEARCH			WM_USER+0x129
+#define NM_COPY_CLIP				WM_USER+0x130
 
 
 
@@ -104,7 +106,7 @@ public:
 	// returns the list index corresponding to the given FirstTen position number.
 	int GetFirstTenIndex( int num );
 
-	void SetNumberOfLinesPerRow(int nLines);
+	void SetNumberOfLinesPerRow(int nLines, bool force);
 	void GetSelectionIndexes(ARRAY &arr);
 	void GetSelectionItemData(ARRAY &arr);
 	void RefreshVisibleRows();
@@ -158,8 +160,13 @@ public:
 
 	void SetSearchText(CString text);
 
-protected:
+	void SetDpiInfo(CDPI *dpi);
+
+	void OnDpiChanged();
+	
 	void LoadCopyOrCutToClipboard();
+
+protected:
 	BOOL GetClipData(int nItem, CClipFormat &Clip);
 	BOOL DrawBitMap(int nItem, CRect &crRect, CDC *pDC, const CString &csDescription);
 	void LoadDittoCopyBufferHotkeys();
@@ -191,6 +198,7 @@ protected:
 	BOOL m_showIfClipWasPasted;
 	CAccels *m_pToolTipActions;
 	CRichEditCtrlEx m_rtfFormater;
+	CDPI *m_windowDpi;
 
 
 	// Generated message map functions

+ 103 - 41
QPasteWnd.cpp

@@ -170,6 +170,7 @@ ON_WM_DESTROY()
 
 //}}AFX_MSG_MAP
 ON_MESSAGE(NM_SEARCH_ENTER_PRESSED, OnSearchEnterKeyPressed)
+ON_MESSAGE(NM_COPY_CLIP, OnCopyClip)
 ON_MESSAGE(NM_END, OnListEnd)
 ON_MESSAGE(CB_SEARCH, OnSearch)
 ON_MESSAGE(NM_DELETE, OnDelete)
@@ -335,14 +336,15 @@ int CQPasteWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
     SetWindowText(_T(QPASTE_TITLE));
 
     m_search.Create(WS_TABSTOP | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, CRect(0, 0, 0, 0), this, ID_EDIT_SEARCH);
+	m_search.SetDpiInfo(&m_DittoWindow.m_dpi);
 	m_search.SetPromptText(theApp.m_Language.GetString(_T("Search"), _T("Search")));
 	SetSearchImages();
 	m_search.LoadPastSearches(CGetSetOptions::GetPastSearchXml());
 
-	CRect rcEditArea(theApp.m_metrics.ScaleX(4), theApp.m_metrics.ScaleY(2), theApp.m_metrics.ScaleX(20), theApp.m_metrics.ScaleY(2));
+	CRect rcEditArea(m_DittoWindow.m_dpi.ScaleX(4), m_DittoWindow.m_dpi.ScaleY(2), m_DittoWindow.m_dpi.ScaleX(20), m_DittoWindow.m_dpi.ScaleY(2));
 	//m_search.SetBorder(rcEditArea);
 
-	CRect rcCloseArea(theApp.m_metrics.ScaleX(85), theApp.m_metrics.ScaleY(3), theApp.m_metrics.ScaleX(99), theApp.m_metrics.ScaleY(15));
+	CRect rcCloseArea(m_DittoWindow.m_dpi.ScaleX(85), m_DittoWindow.m_dpi.ScaleY(3), m_DittoWindow.m_dpi.ScaleX(99), m_DittoWindow.m_dpi.ScaleY(15));
 	//m_search.SetButtonArea(rcCloseArea);
 
     // Create the header control
@@ -351,6 +353,7 @@ int CQPasteWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
         ASSERT(FALSE);
         return -1;
     }
+	m_lstHeader.SetDpiInfo(&m_DittoWindow.m_dpi);
 	m_lstHeader.ShowWindow(SW_SHOW);
 
     ((CWnd*) &m_GroupTree)->CreateEx(NULL, _T("SysTreeView32"), NULL, TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS, CRect(0, 0, 100, 100), this, 0);
@@ -362,18 +365,18 @@ int CQPasteWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
 
     m_ShowGroupsFolderBottom.Create(NULL, WS_CHILD | BS_OWNERDRAW | WS_TABSTOP, CRect(0, 0, 0, 0), this, ID_SHOW_GROUPS_BOTTOM);
     //m_ShowGroupsFolderBottom.LoadBitmaps(IDB_CLOSED_FOLDER, IDB_CLOSED_FOLDER_PRESSED, IDB_CLOSED_FOLDER_FOCUSED);
-	m_ShowGroupsFolderBottom.LoadStdImageDPI(open_folder_24, open_folder_30, open_folder_36, open_folder_42, open_folder_48, _T("PNG"));
+	m_ShowGroupsFolderBottom.LoadStdImageDPI(m_DittoWindow.m_dpi.GetDPIX(), open_folder_24, open_folder_30, open_folder_36, open_folder_42, open_folder_48, _T("PNG"));
     m_ShowGroupsFolderBottom.ShowWindow(SW_SHOW);
 	m_ShowGroupsFolderBottom.SetToolTipText(theApp.m_Language.GetString(_T("GroupsTooltip"), _T("Groups")));
 	m_ShowGroupsFolderBottom.ModifyStyle(WS_TABSTOP, 0);
 	
     m_BackButton.Create(NULL, WS_CHILD | BS_OWNERDRAW | WS_TABSTOP, CRect(0, 0, 0, 0), this, ID_BACK_BUTTON);
-	m_BackButton.LoadStdImageDPI(return_16, return_20, return_24, return_28, return_32, _T("PNG"));
+	m_BackButton.LoadStdImageDPI(m_DittoWindow.m_dpi.GetDPIX(), return_16, return_20, return_24, return_28, return_32, _T("PNG"));
 	m_BackButton.ModifyStyle(WS_TABSTOP, 0);
     m_BackButton.ShowWindow(SW_SHOW);
 
 	m_systemMenu.Create(NULL, WS_CHILD | BS_OWNERDRAW | WS_TABSTOP, CRect(0, 0, 0, 0), this, ID_SYSTEM_BUTTON);
-	m_systemMenu.LoadStdImageDPI(system_menu_2_24, system_menu_2_30, system_menu_2_36, system_menu_2_42, system_menu_2_48, _T("PNG"));
+	m_systemMenu.LoadStdImageDPI(m_DittoWindow.m_dpi.GetDPIX(), system_menu_2_24, system_menu_2_30, system_menu_2_36, system_menu_2_42, system_menu_2_48, _T("PNG"));
 	m_systemMenu.ModifyStyle(WS_TABSTOP, 0);
 	m_systemMenu.ShowWindow(SW_SHOW);
 		
@@ -394,18 +397,7 @@ int CQPasteWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
         return -1;
     }
 
-    m_Alpha.SetWindowHandle(m_hWnd);
-		
-	m_SearchFont.CreateFont(-theApp.m_metrics.PointsToPixels(12), 0, 0, 0, 400, 0, 0, 0, DEFAULT_CHARSET, 3, 2, 1, 34, _T("Segoe UI"));
-    m_search.SetFont(&m_SearchFont);
-	m_search.SetPromptFont(m_SearchFont);
-
-	m_GroupTree.SetFont(&m_SearchFont);
-
-	m_groupFont.CreateFont(-theApp.m_metrics.PointsToPixels(8), 0, 0, 0, 400, 0, 1, 0, DEFAULT_CHARSET, 3, 2, 1, 34, _T("Segoe UI"));
-	m_stGroup.SetFont(&m_groupFont);	
-	m_stGroup.SetBkColor(g_Opt.m_Theme.MainWindowBG());
-	m_stGroup.SetTextColor(RGB(127, 127, 127));
+    m_Alpha.SetWindowHandle(m_hWnd);	
 	
     UpdateFont();
 	
@@ -553,11 +545,11 @@ void CQPasteWnd::SetSearchImages()
 {
 	//int iSourceImageDPIToUse = 96; // We will assume 96 by default.
 
-	//if (theApp.m_metrics.GetDPIX() > 144) 
+	//if (m_DittoWindow.m_dpi.GetDPIX() > 144) 
 	//	iSourceImageDPIToUse = 192;
-	//else if (theApp.m_metrics.GetDPIX() > 120) 
+	//else if (m_DittoWindow.m_dpi.GetDPIX() > 120) 
 	//	iSourceImageDPIToUse = 144;
-	//else if (theApp.m_metrics.GetDPIX() > 96) 
+	//else if (m_DittoWindow.m_dpi.GetDPIX() > 96) 
 	//	iSourceImageDPIToUse = 120;
 
 	//// Now select the right resource to load.
@@ -600,17 +592,17 @@ void CQPasteWnd::MoveControls()
     int cy = crRect.Height();
 
     //Hide the two pixels of space at the top, not sure where this is coming from
-	int topOfListBox = -2;
+	int topOfListBox = 0;
 	
     if(theApp.m_GroupID > 0)
     {
         m_stGroup.ShowWindow(SW_SHOW);
         m_BackButton.ShowWindow(SW_SHOW);
 
-		m_BackButton.MoveWindow(theApp.m_metrics.ScaleX(2), theApp.m_metrics.ScaleY(2), theApp.m_metrics.ScaleX(16), theApp.m_metrics.ScaleY(16));
-		m_stGroup.MoveWindow(theApp.m_metrics.ScaleX(24), theApp.m_metrics.ScaleY(2), cx - theApp.m_metrics.ScaleX(20), theApp.m_metrics.ScaleY(16));
+		m_BackButton.MoveWindow(m_DittoWindow.m_dpi.ScaleX(2), m_DittoWindow.m_dpi.ScaleY(2), m_DittoWindow.m_dpi.ScaleX(16), m_DittoWindow.m_dpi.ScaleY(16));
+		m_stGroup.MoveWindow(m_DittoWindow.m_dpi.ScaleX(24), m_DittoWindow.m_dpi.ScaleY(2), cx - m_DittoWindow.m_dpi.ScaleX(20), m_DittoWindow.m_dpi.ScaleY(16));
 
-		topOfListBox = theApp.m_metrics.ScaleY(20);
+		topOfListBox = m_DittoWindow.m_dpi.ScaleY(20);
 	}
 	else
 	{
@@ -626,14 +618,14 @@ void CQPasteWnd::MoveControls()
 	}*/
 
     int nWidth = cx;
-	int listBoxBottomOffset = theApp.m_metrics.ScaleY(searchRowStart);
+	int listBoxBottomOffset = m_DittoWindow.m_dpi.ScaleY(searchRowStart);
 	
 	int extraSize = 0;
 
 	if(m_showScrollBars == false &&
 		g_Opt.m_showScrollBar == false)
 	{
-		extraSize = ::GetSystemMetrics(SM_CXVSCROLL);
+		extraSize = m_DittoWindow.m_dpi.ScaleX(::GetSystemMetrics(SM_CXVSCROLL));
 
 		CRgn rgnRect;
 		CRect r;
@@ -645,17 +637,17 @@ void CQPasteWnd::MoveControls()
 	}
 
 	m_lstHeader.MoveWindow(0, topOfListBox, cx+extraSize, cy - listBoxBottomOffset-topOfListBox + extraSize+1);
-	m_search.MoveWindow(theApp.m_metrics.ScaleX(34), cy - theApp.m_metrics.ScaleY(searchRowStart-5), cx - theApp.m_metrics.ScaleX(70), theApp.m_metrics.ScaleY(23));
+	m_search.MoveWindow(m_DittoWindow.m_dpi.ScaleX(34), cy - m_DittoWindow.m_dpi.ScaleY(searchRowStart-5), cx - m_DittoWindow.m_dpi.ScaleX(70), m_DittoWindow.m_dpi.ScaleY(23));
 
-	m_systemMenu.MoveWindow(cx - theApp.m_metrics.ScaleX(30), cy - theApp.m_metrics.ScaleX(28), theApp.m_metrics.ScaleX(24), theApp.m_metrics.ScaleY(24));
+	m_systemMenu.MoveWindow(cx - m_DittoWindow.m_dpi.ScaleX(30), cy - m_DittoWindow.m_dpi.ScaleX(28), m_DittoWindow.m_dpi.ScaleX(24), m_DittoWindow.m_dpi.ScaleY(24));
 
-	m_ShowGroupsFolderBottom.MoveWindow(theApp.m_metrics.ScaleX(4), cy - theApp.m_metrics.ScaleX(28), theApp.m_metrics.ScaleX(24), theApp.m_metrics.ScaleY(24));
+	m_ShowGroupsFolderBottom.MoveWindow(m_DittoWindow.m_dpi.ScaleX(4), cy - m_DittoWindow.m_dpi.ScaleX(28), m_DittoWindow.m_dpi.ScaleX(24), m_DittoWindow.m_dpi.ScaleY(24));
 
 	/*if (g_Opt.m_bShowPersistent &&
 		g_Opt.m_bShowAlwaysOnTopWarning)
 	{
 		m_alwaysOnToWarningStatic.ShowWindow(SW_SHOW);
-		m_alwaysOnToWarningStatic.MoveWindow(theApp.m_metrics.ScaleX(2), cy - theApp.m_metrics.ScaleY(18), cx - theApp.m_metrics.ScaleY(4), theApp.m_metrics.ScaleY(17));
+		m_alwaysOnToWarningStatic.MoveWindow(m_DittoWindow.m_dpi.ScaleX(2), cy - m_DittoWindow.m_dpi.ScaleY(18), cx - m_DittoWindow.m_dpi.ScaleY(4), m_DittoWindow.m_dpi.ScaleY(17));
 	}
 	else*/
 	{
@@ -814,7 +806,8 @@ void CQPasteWnd::SaveWindowSize()
 	{
 		CRect rect;
 		GetWindowRectEx(&rect);
-		CGetSetOptions::SetQuickPasteSize(rect.Size());
+		CSize s = rect.Size();
+		CGetSetOptions::SetQuickPasteSize(CSize(m_DittoWindow.m_dpi.UnscaleX(s.cx), m_DittoWindow.m_dpi.UnscaleX(s.cy)));
 		CGetSetOptions::SetQuickPastePoint(rect.TopLeft());
 	}
 }
@@ -837,7 +830,7 @@ BOOL CQPasteWnd::ShowQPasteWindow(BOOL bFillList)
 
 	SetCurrentTransparency();
 
-    m_lstHeader.SetNumberOfLinesPerRow(CGetSetOptions::GetLinesPerRow());
+    m_lstHeader.SetNumberOfLinesPerRow(CGetSetOptions::GetLinesPerRow(), false);
     m_lstHeader.SetShowTextForFirstTenHotKeys(CGetSetOptions::GetShowTextForFirstTenHotKeys());
 	m_lstHeader.SetShowIfClipWasPasted(CGetSetOptions::GetShowIfClipWasPasted());
 
@@ -1055,6 +1048,13 @@ LRESULT CQPasteWnd::OnListMoveSelectionToGroup(WPARAM wParam, LPARAM lParam)
 	return TRUE;
 }
 
+LRESULT CQPasteWnd::OnCopyClip(WPARAM wParam, LPARAM lParam)
+{
+	m_lstHeader.LoadCopyOrCutToClipboard();
+	theApp.IC_Copy();
+	return TRUE;
+}
+
 LRESULT CQPasteWnd::OnSearchEnterKeyPressed(WPARAM wParam, LPARAM lParam)
 {
 	MSG msg;
@@ -1829,33 +1829,33 @@ LRESULT CQPasteWnd::OnSearch(WPARAM wParam, LPARAM lParam)
 ///////////////////////////////////////////////////////////////////////
 void CQPasteWnd::OnMenuLinesperrow1()
 {
-    SetLinesPerRow(1);
+    SetLinesPerRow(1, false);
 }
 
 void CQPasteWnd::OnMenuLinesperrow2()
 {
-    SetLinesPerRow(2);
+    SetLinesPerRow(2, false);
 }
 
 void CQPasteWnd::OnMenuLinesperrow3()
 {
-    SetLinesPerRow(3);
+    SetLinesPerRow(3, false);
 }
 
 void CQPasteWnd::OnMenuLinesperrow4()
 {
-    SetLinesPerRow(4);
+    SetLinesPerRow(4, false);
 }
 
 void CQPasteWnd::OnMenuLinesperrow5()
 {
-    SetLinesPerRow(5);
+    SetLinesPerRow(5, false);
 }
 
-void CQPasteWnd::SetLinesPerRow(int lines)
+void CQPasteWnd::SetLinesPerRow(int lines, bool force)
 {
     CGetSetOptions::SetLinesPerRow(lines);
-    m_lstHeader.SetNumberOfLinesPerRow(lines);
+    m_lstHeader.SetNumberOfLinesPerRow(lines, force);
 
 	ATL::CCritSecLock csLock(m_CritSection.m_sect);
 
@@ -1864,7 +1864,7 @@ void CQPasteWnd::SetLinesPerRow(int lines)
 	m_cf_rtfCache.clear();
 	m_cf_NO_rtfCache.clear();
 
-    FillList();
+    //FillList();
 }
 
 void CQPasteWnd::OnMenuTransparencyNone()
@@ -1998,7 +1998,21 @@ void CQPasteWnd::UpdateFont()
 {
     LOGFONT lf;
     CGetSetOptions::GetFont(lf);
+	lf.lfHeight = m_DittoWindow.m_dpi.PointsToPixels(lf.lfHeight);
     m_lstHeader.SetLogFont(lf);
+
+	m_SearchFont.Detach();
+	m_SearchFont.CreateFont(-m_DittoWindow.m_dpi.PointsToPixels(12), 0, 0, 0, 400, 0, 0, 0, DEFAULT_CHARSET, 3, 2, 1, 34, _T("Segoe UI"));
+	m_search.SetFont(&m_SearchFont);
+	m_search.SetPromptFont(m_SearchFont);
+
+	m_GroupTree.SetFont(&m_SearchFont);
+
+	m_groupFont.Detach();
+	m_groupFont.CreateFont(-m_DittoWindow.m_dpi.PointsToPixels(8), 0, 0, 0, 400, 0, 1, 0, DEFAULT_CHARSET, 3, 2, 1, 34, _T("Segoe UI"));
+	m_stGroup.SetFont(&m_groupFont);
+	m_stGroup.SetBkColor(g_Opt.m_Theme.MainWindowBG());
+	m_stGroup.SetTextColor(RGB(127, 127, 127));
 }
 
 void CQPasteWnd::OnMenuFirsttenhotkeysUsectrlnum()
@@ -2465,11 +2479,16 @@ void CQPasteWnd::OnMenuQuickoptionsFont()
     CFont *pFont = m_lstHeader.GetFont();
     LOGFONT lf;
     pFont->GetLogFont(&lf);
+
+	lf.lfHeight = m_DittoWindow.m_dpi.PixelsToPoints(lf.lfHeight);
+
     CFontDialog dlg(&lf);
     if(dlg.DoModal() == IDOK)
     {
         CGetSetOptions::SetFont(*dlg.m_cf.lpLogFont);
+		(*dlg.m_cf.lpLogFont).lfHeight = m_DittoWindow.m_dpi.PointsToPixels((*dlg.m_cf.lpLogFont).lfHeight);
         m_lstHeader.SetLogFont(*dlg.m_cf.lpLogFont);
+		this->SetLinesPerRow(CGetSetOptions::GetLinesPerRow(), true);
     }
 
     m_bHideWnd = true;
@@ -4924,7 +4943,7 @@ LRESULT CQPasteWnd::OnPostOptions(WPARAM wParam, LPARAM lParam)
 
 	m_lstHeader.SetShowTextForFirstTenHotKeys(CGetSetOptions::GetShowTextForFirstTenHotKeys());
 	m_lstHeader.SetShowIfClipWasPasted(CGetSetOptions::GetShowIfClipWasPasted());
-	m_lstHeader.SetNumberOfLinesPerRow(CGetSetOptions::GetLinesPerRow());
+	m_lstHeader.SetNumberOfLinesPerRow(CGetSetOptions::GetLinesPerRow(), true);
 
 	SetCurrentTransparency();
 
@@ -6613,8 +6632,51 @@ LRESULT CQPasteWnd::OnSearchFocused(WPARAM wParam, LPARAM lParam)
 	return TRUE;
 }
 
+#include <ShellScalingApi.h>
+
+
 LRESULT CQPasteWnd::OnDpiChanged(WPARAM wParam, LPARAM lParam)
 {
+	int dpi = HIWORD(wParam);	
+	m_DittoWindow.OnDpiChanged(this, dpi);
+		
+	RECT* const prcNewWindow = (RECT*)lParam;
+	SetWindowPos(NULL,
+		prcNewWindow->left,
+		prcNewWindow->top,
+		prcNewWindow->right - prcNewWindow->left,
+		prcNewWindow->bottom - prcNewWindow->top,
+		SWP_NOZORDER | SWP_NOACTIVATE);
+	
+	m_systemMenu.Reset();
+	m_systemMenu.LoadStdImageDPI(m_DittoWindow.m_dpi.GetDPIX(), system_menu_2_24, system_menu_2_30, system_menu_2_36, system_menu_2_42, system_menu_2_48, _T("PNG"));
+
+	m_BackButton.Reset();
+	m_BackButton.LoadStdImageDPI(m_DittoWindow.m_dpi.GetDPIX(), return_16, return_20, return_24, return_28, return_32, _T("PNG"));
+
+	m_ShowGroupsFolderBottom.Reset();
+	m_ShowGroupsFolderBottom.LoadStdImageDPI(m_DittoWindow.m_dpi.GetDPIX(), open_folder_24, open_folder_30, open_folder_36, open_folder_42, open_folder_48, _T("PNG"));
+	
+	m_search.OnDpiChanged();
+
+	int t = m_lstHeader.GetTopIndex();
+	m_lstHeader.EnsureVisible(0, FALSE);
+	
+	m_lstHeader.OnDpiChanged();	
+
+	UpdateFont();
+	this->SetLinesPerRow(CGetSetOptions::GetLinesPerRow(), true);
+
+	m_lstHeader.EnsureVisible(t, FALSE);
+
+	MoveControls();
+
+	m_lstHeader.RefreshVisibleRows();
+
+	this->SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
+
+	this->Invalidate();
+	this->RedrawWindow();
 
 	return TRUE;
 }

+ 2 - 1
QPasteWnd.h

@@ -188,7 +188,7 @@ public:
     bool SaveDescription(int nItem, CString text);
 
     //Menu Items
-    void SetLinesPerRow(int lines);
+    void SetLinesPerRow(int lines, bool force);
     void SetTransparency(int percent);
     void OnUpdateLinesPerRow(CCmdUI *pCmdUI, int nValue);
     void OnUpdateTransparency(CCmdUI *pCmdUI, int nValue);
@@ -527,4 +527,5 @@ public:
 	afx_msg LRESULT OnDpiChanged(WPARAM wParam, LPARAM lParam);
 	afx_msg void OnCliporderMovetolast();
 	afx_msg void OnUpdateCliporderMovetolast(CCmdUI *pCmdUI);
+	afx_msg LRESULT OnCopyClip(WPARAM wParam, LPARAM lParam);
 };

+ 51 - 9
QRCodeViewer.cpp

@@ -40,6 +40,9 @@ BEGIN_MESSAGE_MAP(QRCodeViewer, CWnd)
 	ON_WM_CTLCOLOR()
 	ON_WM_WINDOWPOSCHANGING()
 	ON_WM_TIMER()
+	ON_MESSAGE(WM_DPICHANGED, OnDpiChanged)
+	ON_WM_MOVING()
+	ON_WM_ENTERSIZEMOVE()
 END_MESSAGE_MAP()
 
 
@@ -52,6 +55,8 @@ BOOL QRCodeViewer::CreateEx(CWnd *pParentWnd, unsigned char* bitmapData, int ima
 	m_imageSize = imageSize;
 	m_descRowHeight = rowHeight;
 	m_descBackground = CreateSolidBrush(RGB(255, 255, 255));
+	m_logFont = logFont;
+	m_originalFontHeight = logFont.lfHeight;
 
 	if(CWnd::CreateEx(0, szClassName, _T(""), WS_POPUP, 0, 0, 0, 0, NULL, 0, NULL))
 	{	
@@ -79,8 +84,13 @@ BOOL QRCodeViewer::CreateEx(CWnd *pParentWnd, unsigned char* bitmapData, int ima
 		rect.left = parentRect.left;
 		rect.top = parentRect.top;
 
-		rect.right = rect.left + m_DittoWindow.m_lLeftBorder + m_DittoWindow.m_lRightBorder + m_qrCodeDrawer.ImageWidth() + (CGetSetOptions::GetQRCodeBorderPixels() * 2);
-		rect.bottom = rect.top + m_DittoWindow.m_lTopBorder + m_DittoWindow.m_lBottomBorder + rowHeight + 5 + m_qrCodeDrawer.ImageHeight() + (CGetSetOptions::GetQRCodeBorderPixels() * 2);
+		rect.right = rect.left + m_DittoWindow.m_borderSize + m_DittoWindow.m_borderSize + m_qrCodeDrawer.ImageWidth() + (CGetSetOptions::GetQRCodeBorderPixels() * 2);
+		if (m_DittoWindow.m_captionPosition == CAPTION_LEFT ||
+			m_DittoWindow.m_captionPosition == CAPTION_RIGHT)
+		{
+			rect.right += m_DittoWindow.m_captionBorderWidth;
+		}
+		rect.bottom = rect.top + m_DittoWindow.m_borderSize + m_DittoWindow.m_borderSize + rowHeight + 5 + m_qrCodeDrawer.ImageHeight() + (CGetSetOptions::GetQRCodeBorderPixels() * 2);
 		
 		CRect center = CenterRect(rect);
 
@@ -107,8 +117,6 @@ void QRCodeViewer::OnSize(UINT nType, int cx, int cy)
 	this->Invalidate();
 
 	MoveControls();
-
-	m_DittoWindow.DoSetRegion(this);	
 }
 
 void QRCodeViewer::MoveControls()
@@ -120,7 +128,7 @@ void QRCodeViewer::MoveControls()
 
 	if(m_desc.m_hWnd != NULL)
 	{
-		m_desc.MoveWindow(5, cy - m_descRowHeight - 5, cx - 10, m_descRowHeight);
+		m_desc.MoveWindow(m_DittoWindow.m_dpi.ScaleX(5), cy - m_DittoWindow.m_dpi.ScaleX(m_descRowHeight) - m_DittoWindow.m_dpi.ScaleX(5), cx - m_DittoWindow.m_dpi.ScaleX(10), m_DittoWindow.m_dpi.ScaleX(m_descRowHeight));
 	}
 }
 
@@ -130,7 +138,7 @@ void QRCodeViewer::OnPaint()
 
 	CRect thisRect;
 	GetClientRect(thisRect);
-	thisRect.bottom -= m_descRowHeight - 5;
+	thisRect.bottom -= m_DittoWindow.m_dpi.ScaleX(m_descRowHeight) - m_DittoWindow.m_dpi.ScaleX(5);
 	
 	int width = thisRect.Width() - (CGetSetOptions::GetQRCodeBorderPixels() * 2);
 	int height = min(width, (thisRect.Height() - (CGetSetOptions::GetQRCodeBorderPixels() * 2)));
@@ -140,7 +148,7 @@ void QRCodeViewer::OnPaint()
 
 	CRect centerRect = CenterRectFromRect(imageRect, thisRect);
 
-	m_qrCodeDrawer.Draw(&dc, this, centerRect.left, centerRect.top, false, false, width, height);
+	m_qrCodeDrawer.Draw(&dc, m_DittoWindow.m_dpi, this, centerRect.left, centerRect.top, false, false, width, height);
 }
 
 BOOL QRCodeViewer::PreTranslateMessage(MSG *pMsg)
@@ -253,8 +261,6 @@ HBRUSH QRCodeViewer::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
 void QRCodeViewer::OnWindowPosChanging(WINDOWPOS* lpwndpos)
 {
 	CWnd::OnWindowPosChanging(lpwndpos);
-
-	m_DittoWindow.SnapToEdge(this, lpwndpos);
 }
 
 void QRCodeViewer::OnTimer(UINT_PTR nIDEvent)
@@ -273,4 +279,40 @@ void QRCodeViewer::OnTimer(UINT_PTR nIDEvent)
 	}
 
 	CWnd::OnTimer(nIDEvent);
+}
+
+LRESULT QRCodeViewer::OnDpiChanged(WPARAM wParam, LPARAM lParam)
+{
+	int dpi = HIWORD(wParam);
+	m_DittoWindow.OnDpiChanged(this, dpi);
+
+	RECT* const prcNewWindow = (RECT*)lParam;
+	SetWindowPos(NULL,
+		prcNewWindow->left,
+		prcNewWindow->top,
+		prcNewWindow->right - prcNewWindow->left,
+		prcNewWindow->bottom - prcNewWindow->top,
+		SWP_NOZORDER | SWP_NOACTIVATE);
+
+	MoveControls();
+
+	m_logFont.lfHeight = m_DittoWindow.m_dpi.PointsToPixels(m_originalFontHeight);
+
+	m_font.Detach();
+	m_font.CreateFontIndirect(&m_logFont);
+	m_desc.SetFont(&m_font);
+
+	return TRUE;
+}
+
+void QRCodeViewer::OnMoving(UINT fwSide, LPRECT pRect)
+{
+	CWnd::OnMoving(fwSide, pRect);
+	m_snap.OnSnapMoving(m_hWnd, pRect);
+}
+
+void QRCodeViewer::OnEnterSizeMove()
+{
+	m_snap.OnSnapEnterSizeMove(m_hWnd);
+	CWnd::OnEnterSizeMove();
 }

+ 7 - 0
QRCodeViewer.h

@@ -2,6 +2,7 @@
 
 #include "GdipButton.h"
 #include "DittoWindow.h"
+#include "SnapWindow.h"
 // QRCodeViewer
 
 class QRCodeViewer : public CWnd
@@ -34,6 +35,9 @@ protected:
 	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
 	afx_msg void OnWindowPosChanging(WINDOWPOS* lpwndpos);
 	afx_msg void OnTimer(UINT_PTR nIDEvent);
+	afx_msg LRESULT OnDpiChanged(WPARAM wParam, LPARAM lParam);
+	afx_msg void OnMoving(UINT fwSide, LPRECT pRect);
+	afx_msg void OnEnterSizeMove();
 
 	unsigned char* m_bitmapData;
 	int m_imageSize;
@@ -42,6 +46,9 @@ protected:
 	int m_descRowHeight;
 	CFont m_font;
 	HBRUSH m_descBackground;
+	LOGFONT m_logFont;
+	int m_originalFontHeight;
+	SnapWindow m_snap;
 
 	void MoveControls();
 };

+ 15 - 0
QuickPaste.cpp

@@ -207,6 +207,8 @@ void CQuickPaste::ShowQPasteWnd(CWnd *pParent, bool bAtPrevPos, bool bFromKeyboa
 		Log(StrF(_T("Invalid initial size %d %d %d %d, Centered Window %d %d %d %d"), orig.left, orig.top, orig.right, orig.bottom, crRect.left, crRect.top, crRect.right, crRect.bottom));
 	}	
 	
+	bool adjustRect = false;
+
 	if( !IsWindow(m_pwndPaste->m_hWnd) )
 	{
 		CWnd *pLocalParent = pParent;
@@ -217,6 +219,8 @@ void CQuickPaste::ShowQPasteWnd(CWnd *pParent, bool bAtPrevPos, bool bFromKeyboa
 		}
 
 		VERIFY( m_pwndPaste->Create(crRect, pLocalParent) );
+
+		adjustRect = true;
 	}	
 
 	//If minimized
@@ -229,6 +233,12 @@ void CQuickPaste::ShowQPasteWnd(CWnd *pParent, bool bAtPrevPos, bool bFromKeyboa
 			bAtPrevPos ||
 			forceMoveWindow)
 		{
+			if (adjustRect)
+			{
+				crRect.right = crRect.left + m_pwndPaste->m_DittoWindow.m_dpi.ScaleX(crRect.Width());
+				crRect.bottom = crRect.top + m_pwndPaste->m_DittoWindow.m_dpi.ScaleY(crRect.Height());
+			}
+
 			m_pwndPaste->MoveWindow(crRect);
 		}
 	}
@@ -239,6 +249,11 @@ void CQuickPaste::ShowQPasteWnd(CWnd *pParent, bool bAtPrevPos, bool bFromKeyboa
 			bAtPrevPos ||
 			forceMoveWindow)
 		{
+			if (adjustRect)
+			{
+				crRect.right = crRect.left + m_pwndPaste->m_DittoWindow.m_dpi.ScaleX(crRect.Width());
+				crRect.bottom = crRect.top + m_pwndPaste->m_DittoWindow.m_dpi.ScaleY(crRect.Height());
+			}
 			m_pwndPaste->MoveWindow(crRect);
 		}
 

+ 2 - 2
StdAfx.h

@@ -19,8 +19,8 @@
 
 #define HITTEST_RET LRESULT
 
-#define _WIN32_WINNT 0x0605
-#define WINVER 0x0605
+#define _WIN32_WINNT 0x0A00
+#define WINVER 0x0A00
 
 #define VC_EXTRALEAN		// Exclude rarely-used stuff from Windows headers
 

+ 47 - 10
SymbolEdit.cpp

@@ -40,10 +40,10 @@ CSymbolEdit::CSymbolEdit() :
 	m_mouseHoveringOverSearches = false;
 	m_mouseDownOnClose = false;
 	m_mouseHoveringOverClose = false;
+	m_windowDpi = NULL;
 
 	//m_searchButton.LoadStdImageDPI(Search_16, Search_20, Search_24, Search_32, _T("PNG"));
-	m_closeButton.LoadStdImageDPI(search_close_16, Search_20, Search_24, Search_28, Search_32, _T("PNG"));
-	m_searchesButton.LoadStdImageDPI(down_16, down_20, down_24, down_28, down_32, _T("PNG"));
+	
 }
 
 CSymbolEdit::~CSymbolEdit()
@@ -84,7 +84,23 @@ BOOL CSymbolEdit::PreTranslateMessage(MSG* pMsg)
 			Cut();
 			return TRUE;
 		case 'C':
-			Copy();
+			{
+				int startChar;
+				int endChar;
+				this->GetSel(startChar, endChar);
+				if (startChar == endChar)
+				{
+					CWnd *pWnd = GetParent();
+					if (pWnd)
+					{
+						pWnd->SendMessage(NM_COPY_CLIP, pMsg->wParam, pMsg->lParam);
+					}
+				}
+				else
+				{
+					Copy();
+				}
+			}
 			return TRUE;
 		case 'V':
 			Paste();
@@ -410,7 +426,10 @@ void CSymbolEdit::RecalcLayout()
 	}
 	else
 	{
-		SetMargins(4, theApp.m_metrics.ScaleX(34));
+		if (m_windowDpi != NULL)
+		{
+			SetMargins(4, m_windowDpi->ScaleX(34));
+		}
 	}
 }
 
@@ -488,7 +507,7 @@ void CSymbolEdit::OnPaint()
 	if (text.GetLength() == 0 && m_strPromptText.GetLength() > 0)
 	{
 		//if we aren't showing the close icon, then use the full space
-		textRect.right += theApp.m_metrics.ScaleX(16);
+		textRect.right += m_windowDpi->ScaleX(16);
 		//textRect.right -= LOWORD(margins);
 
 		oldFont = dc.SelectObject(&m_fontPrompt);
@@ -503,9 +522,9 @@ void CSymbolEdit::OnPaint()
 	int right = rect.right;
 	if ((text.GetLength() > 0 || this == GetFocus()))
 	{
-		m_searchesButtonRect.SetRect(rect.right - theApp.m_metrics.ScaleX(18), 0, rect.right, rect.bottom);
-		right = rect.right - theApp.m_metrics.ScaleX(18);
-		m_searchesButton.Draw(&dc, this, m_searchesButtonRect.left, 4, m_mouseHoveringOverSearches, m_mouseDownOnSearches);
+		m_searchesButtonRect.SetRect(rect.right - m_windowDpi->ScaleX(18), 0, rect.right, rect.bottom);
+		right = rect.right - m_windowDpi->ScaleX(18);
+		m_searchesButton.Draw(&dc, *m_windowDpi, this, m_searchesButtonRect.left, 4, m_mouseHoveringOverSearches, m_mouseDownOnSearches);
 	}
 	else
 	{
@@ -517,8 +536,8 @@ void CSymbolEdit::OnPaint()
 	{
 		OutputDebugString(_T("showing close button\n"));
 
-		m_closeButtonRect.SetRect(right - theApp.m_metrics.ScaleX(16), 0, right, rect.bottom);
-		m_closeButton.Draw(&dc, this, m_closeButtonRect.left, 4, m_mouseHoveringOverClose, m_mouseDownOnClose);
+		m_closeButtonRect.SetRect(right - m_windowDpi->ScaleX(16), 0, right, rect.bottom);
+		m_closeButton.Draw(&dc, *m_windowDpi, this, m_closeButtonRect.left, 4, m_mouseHoveringOverClose, m_mouseDownOnClose);
 	}
 	else
 	{
@@ -746,4 +765,22 @@ bool CSymbolEdit::ApplyLastSearch()
 	}
 
 	return ret;
+}
+
+void CSymbolEdit::OnDpiChanged()
+{
+	SetDpiInfo(m_windowDpi);
+}
+
+void CSymbolEdit::SetDpiInfo(CDPI *dpi)
+{ 
+	m_windowDpi = dpi; 
+
+	m_closeButton.Reset();
+	m_closeButton.LoadStdImageDPI(m_windowDpi->GetDPIX(), search_close_16, Search_20, Search_24, Search_28, Search_32, _T("PNG"));
+
+	m_searchesButton.Reset();
+	m_searchesButton.LoadStdImageDPI(m_windowDpi->GetDPIX(), down_16, down_20, down_24, down_28, down_32, _T("PNG"));
+
+	RecalcLayout();
 }

+ 7 - 0
SymbolEdit.h

@@ -28,6 +28,7 @@
 
 #include "GdiImageDrawer.h"
 #include "Accels.h"
+#include "DPI.h"
 
 // CSymbolEdit
 
@@ -71,6 +72,10 @@ public:
 	CString SavePastSearches();
 	void LoadPastSearches(CString values);
 
+	void SetDpiInfo(CDPI *dpi);
+
+	void OnDpiChanged();
+
 protected:
 	
 	//CGdiImageDrawer m_searchButton;
@@ -91,6 +96,8 @@ protected:
 	void RecalcLayout();
 	virtual void PreSubclassWindow();
 
+	CDPI *m_windowDpi;
+
 	afx_msg void OnSize(UINT nType, int cx, int cy);
 	afx_msg LRESULT OnSetFont(WPARAM wParam, LPARAM lParam);
 	//afx_msg LRESULT OnMenuExit(WPARAM wParam, LPARAM lParam);

+ 68 - 15
ToolTipEx.cpp

@@ -62,6 +62,9 @@ ON_COMMAND(ID_FIRST_WRAPTEXT, &CToolTipEx::OnFirstWraptext)
 ON_WM_WINDOWPOSCHANGING()
 ON_COMMAND(ID_FIRST_ALWAYSONTOP, &CToolTipEx::OnFirstAlwaysontop)
 ON_NOTIFY(EN_MSGFILTER, 1, &CToolTipEx::OnEnMsgfilterRichedit21)
+ON_MESSAGE(WM_DPICHANGED, OnDpiChanged)
+ON_WM_MOVING()
+ON_WM_ENTERSIZEMOVE()
 END_MESSAGE_MAP()
 
 
@@ -111,13 +114,13 @@ BOOL CToolTipEx::Create(CWnd *pParentWnd)
     SetLogFont(GetSystemToolTipFont(), FALSE);
 
 	m_optionsButton.Create(NULL, WS_CHILD | BS_OWNERDRAW | WS_TABSTOP, CRect(0, 0, 0, 0), this, 2);
-	m_optionsButton.LoadStdImageDPI(IDB_COG_16_16, IDB_COG_20_20, IDB_COG_24_24, cog_28, IDB_COG_32_32, _T("PNG"));
+	m_optionsButton.LoadStdImageDPI(m_DittoWindow.m_dpi.GetDPIX(), IDB_COG_16_16, IDB_COG_20_20, IDB_COG_24_24, cog_28, IDB_COG_32_32, _T("PNG"));
 	m_optionsButton.SetToolTipText(theApp.m_Language.GetString(_T("DescriptionOptionsTooltip"), _T("Description Options")));
 	m_optionsButton.ShowWindow(SW_SHOW);
 
 	m_clipDataStatic.Create(_T("some text"), WS_CHILD | WS_VISIBLE | SS_SIMPLE, CRect(0, 0, 0, 0), this, 3);
 
-	m_clipDataFont.CreateFont(-theApp.m_metrics.PointsToPixels(8), 0, 0, 0, 400, 0, 0, 0, DEFAULT_CHARSET, 3, 2, 1, 34, _T("Segoe UI"));
+	m_clipDataFont.CreateFont(-m_DittoWindow.m_dpi.PointsToPixels(8), 0, 0, 0, 400, 0, 0, 0, DEFAULT_CHARSET, 3, 2, 1, 34, _T("Segoe UI"));
 	m_clipDataStatic.SetFont(&m_clipDataFont);
 	m_clipDataStatic.SetBkColor(g_Opt.m_Theme.DescriptionWindowBG());
 	m_clipDataStatic.SetTextColor(RGB(80, 80, 80));
@@ -151,8 +154,8 @@ BOOL CToolTipEx::Show(CPoint point)
 		rect.top = point.y;
 		CSize size;
 		CGetSetOptions::GetDescWndSize(size);
-		rect.right = rect.left + size.cx;
-		rect.bottom = rect.top + size.cy;
+		rect.right = rect.left + m_DittoWindow.m_dpi.ScaleX(size.cx);
+		rect.bottom = rect.top + m_DittoWindow.m_dpi.ScaleY(size.cy);
 
 		EnsureWindowVisible(&rect);
 	}
@@ -183,8 +186,8 @@ BOOL CToolTipEx::Show(CPoint point)
 			rect.bottom = rect.top + lNewHeight;
 		}
 
-		rect.right += CAPTION_BORDER * 2;
-		rect.bottom += CAPTION_BORDER * 2;
+		//rect.right += CAPTION_BORDER * 2;
+		//rect.bottom += CAPTION_BORDER * 2;
 
 		
 
@@ -306,7 +309,8 @@ void CToolTipEx::SaveWindowSize()
 			this->GetWindowRect(&rect);
 		}
 
-		CGetSetOptions::SetDescWndSize(rect.Size());
+		CSize s = rect.Size();
+		CGetSetOptions::SetDescWndSize(CSize(m_DittoWindow.m_dpi.UnscaleX(s.cx), m_DittoWindow.m_dpi.UnscaleX(s.cy)));
 		CGetSetOptions::SetDescWndPoint(rect.TopLeft());
 
 		OutputDebugString(_T("Saving tooltip size"));
@@ -661,18 +665,22 @@ void CToolTipEx::OnSize(UINT nType, int cx, int cy)
         return ;
     }
 
-    CRect cr;
-    GetClientRect(cr);
-    cr.DeflateRect(0, 0, 0, theApp.m_metrics.ScaleY(21));
-    m_RichEdit.MoveWindow(cr);
+	MoveControls();
+}
+
+void CToolTipEx::MoveControls()
+{
+	CRect cr;
+	GetClientRect(cr);
+	cr.DeflateRect(0, 0, 0, m_DittoWindow.m_dpi.ScaleY(21));
+	m_RichEdit.MoveWindow(cr);
 	m_imageViewer.MoveWindow(cr);
 
-	m_optionsButton.MoveWindow(cr.left, cr.bottom + theApp.m_metrics.ScaleY(2), theApp.m_metrics.ScaleX(17), theApp.m_metrics.ScaleY(17));
+	m_optionsButton.MoveWindow(cr.left, cr.bottom + m_DittoWindow.m_dpi.ScaleY(2), m_DittoWindow.m_dpi.ScaleX(17), m_DittoWindow.m_dpi.ScaleY(17));
 
-	m_clipDataStatic.MoveWindow(cr.left + theApp.m_metrics.ScaleX(19), cr.bottom + theApp.m_metrics.ScaleY(2), cr.Width() - cr.left + theApp.m_metrics.ScaleX(19), theApp.m_metrics.ScaleY(17));
+	m_clipDataStatic.MoveWindow(cr.left + m_DittoWindow.m_dpi.ScaleX(19), cr.bottom + m_DittoWindow.m_dpi.ScaleY(2), cr.Width() - cr.left + m_DittoWindow.m_dpi.ScaleX(19), m_DittoWindow.m_dpi.ScaleY(17));
 
 	this->Invalidate();
-	m_DittoWindow.DoSetRegion(this);
 
 	if (m_saveWindowLockout == false)
 	{
@@ -1104,7 +1112,7 @@ void CToolTipEx::OnWindowPosChanging(WINDOWPOS* lpwndpos)
 {
 	CWnd::OnWindowPosChanging(lpwndpos);
 
-	m_DittoWindow.SnapToEdge(this, lpwndpos);
+	//m_DittoWindow.SnapToEdge(this, lpwndpos);
 }
 
 
@@ -1163,4 +1171,49 @@ void CToolTipEx::OnEnMsgfilterRichedit21(NMHDR *pNMHDR, LRESULT *pResult)
 	}
 
 	*pResult = 0;
+}
+
+LRESULT CToolTipEx::OnDpiChanged(WPARAM wParam, LPARAM lParam)
+{
+	int dpi = HIWORD(wParam);
+	m_DittoWindow.OnDpiChanged(this, dpi);
+
+	RECT* const prcNewWindow = (RECT*)lParam;
+	SetWindowPos(NULL,
+		prcNewWindow->left,
+		prcNewWindow->top,
+		prcNewWindow->right - prcNewWindow->left,
+		prcNewWindow->bottom - prcNewWindow->top,
+		SWP_NOZORDER | SWP_NOACTIVATE);
+
+	m_optionsButton.Reset();
+	m_optionsButton.LoadStdImageDPI(m_DittoWindow.m_dpi.GetDPIX(), IDB_COG_16_16, IDB_COG_20_20, IDB_COG_24_24, cog_28, IDB_COG_32_32, _T("PNG"));
+
+	m_clipDataFont.Detach();
+	m_clipDataFont.CreateFont(-m_DittoWindow.m_dpi.PointsToPixels(8), 0, 0, 0, 400, 0, 0, 0, DEFAULT_CHARSET, 3, 2, 1, 34, _T("Segoe UI"));
+	m_clipDataStatic.SetFont(&m_clipDataFont);
+	m_clipDataStatic.SetBkColor(g_Opt.m_Theme.DescriptionWindowBG());
+	m_clipDataStatic.SetTextColor(RGB(80, 80, 80));
+
+	this->MoveControls();
+	this->Invalidate();
+	this->UpdateWindow();
+
+	return TRUE;
+}
+
+void CToolTipEx::OnMoving(UINT fwSide, LPRECT pRect)
+{
+	CWnd::OnMoving(fwSide, pRect);
+
+	m_snap.OnSnapMoving(m_hWnd, pRect);
+	// TODO: Add your message handler code here
+}
+
+
+void CToolTipEx::OnEnterSizeMove()
+{
+	m_snap.OnSnapEnterSizeMove(m_hWnd);
+
+	CWnd::OnEnterSizeMove();
 }

+ 6 - 0
ToolTipEx.h

@@ -7,6 +7,7 @@
 #include "ImageViewer.h"
 #include "GroupStatic.h"
 #include "Accels.h"
+#include "SnapWindow.h"
 
 class CToolTipEx : public CWnd
 {
@@ -50,6 +51,7 @@ public:
 	void UpdateMenuShortCut(CMenu *subMenu, int id, DWORD action);
 
 	void DoSearch();
+	void MoveControls();
 
 
 // Overrides
@@ -89,6 +91,7 @@ protected:
 	CAccels *m_pToolTipActions;
 	bool m_bMaxSetTimer;
 	int m_lDelayMaxSeconds;
+	SnapWindow m_snap;
 	
 
 protected:
@@ -129,4 +132,7 @@ public:
 	afx_msg void OnFirstAlwaysontop();
 	virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
 	void OnEnMsgfilterRichedit21(NMHDR *pNMHDR, LRESULT *pResult);
+	afx_msg LRESULT OnDpiChanged(WPARAM wParam, LPARAM lParam);
+	afx_msg void OnMoving(UINT fwSide, LPRECT pRect);
+	afx_msg void OnEnterSizeMove();
 };

+ 29 - 3
WndEx.cpp

@@ -62,6 +62,8 @@ BEGIN_MESSAGE_MAP(CWndEx, CWnd)
 	ON_WM_INITMENUPOPUP() 
 //}}AFX_MSG_MAP
 ON_WM_SIZE()
+ON_WM_MOVING()
+ON_WM_ENTERSIZEMOVE()
 END_MESSAGE_MAP()
 
 
@@ -99,6 +101,13 @@ int CWndEx::OnCreate(LPCREATESTRUCT lpCreateStruct)
 	m_DittoWindow.m_bDrawMinimize = false;
 	m_DittoWindow.m_bDrawMaximize = false;
 
+	SetWindowPos(NULL,
+		lpCreateStruct->x,
+		lpCreateStruct->y,
+		m_DittoWindow.m_dpi.ScaleX(lpCreateStruct->cx),
+		m_DittoWindow.m_dpi.ScaleY(lpCreateStruct->cy),
+		SWP_NOZORDER | SWP_NOACTIVATE);
+
 	SetCaptionColorActive(false, TRUE);
 	m_DittoWindow.SetCaptionOn(this, CGetSetOptions::GetCaptionPos(), true, g_Opt.m_Theme.GetCaptionSize(), g_Opt.m_Theme.GetCaptionFontSize());
 	SetAutoMaxDelay(CGetSetOptions::GetAutoMaxDelay());
@@ -274,14 +283,14 @@ void CWndEx::OnWindowPosChanging(WINDOWPOS* lpwndpos)
 		m_bMaxSetTimer = false;
 	}
 
-	m_DittoWindow.SnapToEdge(this, lpwndpos);
+	//m_DittoWindow.SnapToEdge(this, lpwndpos);
 }
 
 void CWndEx::OnSize(UINT nType, int cx, int cy)
 {
 	CWnd::OnSize(nType, cx, cy);
 	
-	m_DittoWindow.DoSetRegion(this);
+	//m_DittoWindow.DoSetRegion(this);
 }
 
 void CWndEx::OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex, BOOL bSysMenu)
@@ -309,4 +318,21 @@ void CWndEx::SetCustomWindowTitle(CString title)
 void CWndEx::MinMaxWindow(long lOption)
 {
 	m_DittoWindow.MinMaxWindow(this, lOption);
-}
+}
+
+
+void CWndEx::OnMoving(UINT fwSide, LPRECT pRect)
+{
+	CWnd::OnMoving(fwSide, pRect);
+
+	m_snap.OnSnapMoving(m_hWnd, pRect);
+	// TODO: Add your message handler code here
+}
+
+
+void CWndEx::OnEnterSizeMove()
+{
+	m_snap.OnSnapEnterSizeMove(m_hWnd);
+
+	CWnd::OnEnterSizeMove();
+}

+ 6 - 1
WndEx.h

@@ -9,6 +9,7 @@
 
 #include "DittoWindow.h"
 #include "GdipButton.h"
+#include "SnapWindow.h"
 
 #define	SWAP_MIN_MAX			1
 #define FORCE_MIN				2
@@ -49,12 +50,14 @@ public:
 
 	int GetCaptionSize() { return m_DittoWindow.m_captionBorderWidth; }
 
-protected:
 	CDittoWindow m_DittoWindow;
+
+protected:	
 	
 	bool m_bMaxSetTimer;	
 	int m_lDelayMaxSeconds;
 	CToolTipCtrl m_toolTip;
+	SnapWindow m_snap;
 
 // Implementation
 public:
@@ -78,6 +81,8 @@ protected:
 	DECLARE_MESSAGE_MAP()
 public:
 	afx_msg void OnSize(UINT nType, int cx, int cy);
+	afx_msg void OnMoving(UINT fwSide, LPRECT pRect);
+	afx_msg void OnEnterSizeMove();
 };
 
 /////////////////////////////////////////////////////////////////////////////