diff options
| author | Neil <nyamatongwe@gmail.com> | 2020-05-19 19:52:33 +1000 | 
|---|---|---|
| committer | Neil <nyamatongwe@gmail.com> | 2020-05-19 19:52:33 +1000 | 
| commit | 0f89a8d668177c8df38a8947d7d1a7f63abaa15a (patch) | |
| tree | 3bce80c49545e8c5d195189e1cc1c5ed287f15cc /win32 | |
| parent | 05498786fcc7fd6ef18be4b842df16769f4a29cd (diff) | |
| download | scintilla-mirror-0f89a8d668177c8df38a8947d7d1a7f63abaa15a.tar.gz | |
Bug [#2171]. Implement per-monitor DPI Awareness on Windows.
Diffstat (limited to 'win32')
| -rw-r--r-- | win32/PlatWin.cxx | 59 | ||||
| -rw-r--r-- | win32/PlatWin.h | 2 | ||||
| -rw-r--r-- | win32/ScintillaWin.cxx | 21 | 
3 files changed, 61 insertions, 21 deletions
| diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index f09cdfcf1..d4d7b8026 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -243,6 +243,14 @@ void SetWindowPointer(HWND hWnd, void *ptr) noexcept {  namespace { +using GetDpiForWindowSig = UINT(WINAPI *)(HWND hwnd); +GetDpiForWindowSig fnGetDpiForWindow = nullptr; + +void LoadDpiForWindow() noexcept { +	HMODULE user32 = ::GetModuleHandleW(L"user32.dll"); +	fnGetDpiForWindow = DLLFunction<GetDpiForWindowSig>(user32, "GetDpiForWindow"); +} +  HINSTANCE hinstPlatformRes {};  HCURSOR reverseArrowCursor {}; @@ -415,6 +423,16 @@ public:  };  typedef VarBuffer<XYPOSITION, stackBufferLength> TextPositions; +UINT DpiForWindow(WindowID wid) noexcept { +	if (fnGetDpiForWindow) { +		return fnGetDpiForWindow(HwndFromWindowID(wid)); +	} +	HDC hdcMeasure = ::CreateCompatibleDC({}); +	const UINT scale = ::GetDeviceCaps(hdcMeasure, LOGPIXELSY); +	::DeleteDC(hdcMeasure); +	return scale; +} +  class SurfaceGDI : public Surface {  	bool unicodeMode=false;  	HDC hdc{}; @@ -426,6 +444,9 @@ class SurfaceGDI : public Surface {  	HFONT fontOld{};  	HBITMAP bitmap{};  	HBITMAP bitmapOld{}; + +	int logPixelsY = 72; +  	int maxWidthMeasure = INT_MAX;  	// There appears to be a 16 bit string length limit in GDI on NT.  	int maxLenText = 65535; @@ -537,20 +558,22 @@ bool SurfaceGDI::Initialised() {  	return hdc != 0;  } -void SurfaceGDI::Init(WindowID) { +void SurfaceGDI::Init(WindowID wid) {  	Release();  	hdc = ::CreateCompatibleDC({});  	hdcOwned = true;  	::SetTextAlign(hdc, TA_BASELINE); +	logPixelsY = DpiForWindow(wid);  } -void SurfaceGDI::Init(SurfaceID sid, WindowID) { +void SurfaceGDI::Init(SurfaceID sid, WindowID wid) {  	Release();  	hdc = static_cast<HDC>(sid);  	::SetTextAlign(hdc, TA_BASELINE); +	logPixelsY = DpiForWindow(wid);  } -void SurfaceGDI::InitPixMap(int width, int height, Surface *surface_, WindowID) { +void SurfaceGDI::InitPixMap(int width, int height, Surface *surface_, WindowID wid) {  	Release();  	SurfaceGDI *psurfOther = dynamic_cast<SurfaceGDI *>(surface_);  	// Should only ever be called with a SurfaceGDI, not a SurfaceD2D @@ -562,6 +585,7 @@ void SurfaceGDI::InitPixMap(int width, int height, Surface *surface_, WindowID)  	::SetTextAlign(hdc, TA_BASELINE);  	SetUnicodeMode(psurfOther->unicodeMode);  	SetDBCSMode(psurfOther->codePage); +	logPixelsY = DpiForWindow(wid);  }  void SurfaceGDI::PenColour(ColourDesired fore) { @@ -599,7 +623,7 @@ void SurfaceGDI::SetFont(const Font &font_) noexcept {  }  int SurfaceGDI::LogPixelsY() { -	return ::GetDeviceCaps(hdc, LOGPIXELSY); +	return logPixelsY;  }  int SurfaceGDI::DeviceHeightFont(int points) { @@ -992,8 +1016,6 @@ class SurfaceD2D : public Surface {  	ID2D1SolidColorBrush *pBrush;  	int logPixelsY; -	float dpiScaleX; -	float dpiScaleY;  	void Clear() noexcept;  	void SetFont(const Font &font_); @@ -1007,7 +1029,7 @@ public:  	SurfaceD2D &operator=(SurfaceD2D &&) = delete;  	~SurfaceD2D() override; -	void SetScale(); +	void SetScale(WindowID wid);  	void Init(WindowID wid) override;  	void Init(SurfaceID sid, WindowID wid) override;  	void InitPixMap(int width, int height, Surface *surface_, WindowID wid) override; @@ -1078,8 +1100,6 @@ SurfaceD2D::SurfaceD2D() noexcept :  	pBrush = nullptr;  	logPixelsY = 72; -	dpiScaleX = 1.0; -	dpiScaleY = 1.0;  }  SurfaceD2D::~SurfaceD2D() { @@ -1110,12 +1130,8 @@ void SurfaceD2D::Release() {  	Clear();  } -void SurfaceD2D::SetScale() { -	HDC hdcMeasure = ::CreateCompatibleDC({}); -	logPixelsY = ::GetDeviceCaps(hdcMeasure, LOGPIXELSY); -	dpiScaleX = ::GetDeviceCaps(hdcMeasure, LOGPIXELSX) / 96.0f; -	dpiScaleY = logPixelsY / 96.0f; -	::DeleteDC(hdcMeasure); +void SurfaceD2D::SetScale(WindowID wid) { +	logPixelsY = DpiForWindow(wid);  }  bool SurfaceD2D::Initialised() { @@ -1126,20 +1142,20 @@ HRESULT SurfaceD2D::FlushDrawing() {  	return pRenderTarget->Flush();  } -void SurfaceD2D::Init(WindowID /* wid */) { +void SurfaceD2D::Init(WindowID wid) {  	Release(); -	SetScale(); +	SetScale(wid);  } -void SurfaceD2D::Init(SurfaceID sid, WindowID) { +void SurfaceD2D::Init(SurfaceID sid, WindowID wid) {  	Release(); -	SetScale(); +	SetScale(wid);  	pRenderTarget = static_cast<ID2D1RenderTarget *>(sid);  } -void SurfaceD2D::InitPixMap(int width, int height, Surface *surface_, WindowID) { +void SurfaceD2D::InitPixMap(int width, int height, Surface *surface_, WindowID wid) {  	Release(); -	SetScale(); +	SetScale(wid);  	SurfaceD2D *psurfOther = dynamic_cast<SurfaceD2D *>(surface_);  	// Should only ever be called with a SurfaceD2D, not a SurfaceGDI  	PLATFORM_ASSERT(psurfOther); @@ -3312,6 +3328,7 @@ void Platform::Assert(const char *c, const char *file, int line) {  void Platform_Initialise(void *hInstance) {  	hinstPlatformRes = static_cast<HINSTANCE>(hInstance); +	LoadDpiForWindow();  	LoadReverseArrowCursor();  	ListBoxX_Register();  } diff --git a/win32/PlatWin.h b/win32/PlatWin.h index 9d17dff69..5ce12b6c0 100644 --- a/win32/PlatWin.h +++ b/win32/PlatWin.h @@ -52,6 +52,8 @@ T DLLFunction(HMODULE hModule, LPCSTR lpProcName) noexcept {  	return fp;  } +UINT DpiForWindow(WindowID wid) noexcept; +  #if defined(USE_D2D)  extern bool LoadD2D();  extern ID2D1Factory *pD2DFactory; diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 01ffcbe76..046ff7f10 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -96,6 +96,10 @@  #define WM_UNICHAR                      0x0109  #endif +#ifndef WM_DPICHANGED +#define WM_DPICHANGED 0x02E0 +#endif +  #ifndef UNICODE_NOCHAR  #define UNICODE_NOCHAR                  0xFFFF  #endif @@ -282,6 +286,8 @@ class ScintillaWin :  	unsigned int linesPerScroll;	///< Intellimouse support  	int wheelDelta; ///< Wheel delta from roll +	UINT dpi = 72; +  	HRGN hRgnUpdate;  	bool hasOKText; @@ -337,6 +343,8 @@ class ScintillaWin :  	Sci::Position TargetAsUTF8(char *text) const;  	Sci::Position EncodedFromUTF8(const char *utf8, char *encoded) const; +	void CheckDpiChanged(); +  	bool PaintDC(HDC hdc);  	sptr_t WndPaint(); @@ -847,6 +855,14 @@ Sci::Position ScintillaWin::EncodedFromUTF8(const char *utf8, char *encoded) con  	}  } +void ScintillaWin::CheckDpiChanged() { +	const UINT dpiNow = DpiForWindow(wMain.GetID()); +	if (dpi != dpiNow) { +		dpi = dpiNow; +		InvalidateStyleData(); +	} +} +  bool ScintillaWin::PaintDC(HDC hdc) {  	if (technology == SC_TECHNOLOGY_DEFAULT) {  		AutoSurface surfaceWindow(hdc, this); @@ -877,6 +893,7 @@ bool ScintillaWin::PaintDC(HDC hdc) {  }  sptr_t ScintillaWin::WndPaint() { +	CheckDpiChanged();  	//ElapsedPeriod ep;  	// Redirect assertions to debug output and save current state @@ -1897,6 +1914,10 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam  			InvalidateStyleData();  			break; +		case WM_DPICHANGED: +			InvalidateStyleRedraw(); +			break; +  		case WM_CONTEXTMENU:  			return ShowContextMenu(iMessage, wParam, lParam); | 
