Hello,
First I would like to thank you for the (almost) complete support of HighDPI environments.
I found some problems, which should be addressed in the upcoming release.
Problem:
Two monitors, one 4K 40" is running native 3840x2160, no text resizing, everything is at 100%. This is the MAIN desktop ( important ).
The other monitor is a 24" at 1920x1080, but this one was set to text scaling of 125%. So the DPI factor here is 1.25
When I move the app window from the MAIN monitor to the other one, the internal scaling factor of XtremeToolkit still reports 1.00, which is not correct. Digging into the code, it's clear why, you guys get the DPI factor from the main desktop monitor.
void CXTPDpi::Init() { if (!m_bInitialized) { HDC hdc = ::GetDC(NULL);
That's a problem, you should always use the app windows monitor as the source!
Another problem is the font height calculation in the CXTPPaintManager.
The Statusbar doesn't change the font too, so the Coders should check the code there also.
Because we use quite a few custom made controls in our app, we have already the infrastructure to detect DPI changes. Here are some parts of the code we're using. It's stripped down a bit, it should be easy to reuse.
We modified /extended the Toolkit's code in:
void CXTPPaintManager::UpdateFonts() void CXTPDpi::Init(int dpi)
Modified code is tagged with ANKHOR
Here's the source:
double AnkhorGetDPI(CWnd * cwnd) { double factor; CDC * pDC = cwnd->GetDC(); factor = ::GetDeviceCaps(pDC->m_hDC, LOGPIXELSY); cwnd->ReleaseDC(pDC);
while (cwnd->GetParent() != NULL) cwnd = cwnd->GetParent();
FuncGetDpiForMonitor pGetDpiForMonitor = (FuncGetDpiForMonitor)GetProcAddress(GetModuleHandle(_T("Shcore.dll")), "GetDpiForMonitor"); if (pGetDpiForMonitor != NULL) { UINT dpiX, dpiY; pGetDpiForMonitor(MonitorFromWindow(cwnd->GetSafeHwnd(), MONITOR_DEFAULTTONEAREST), 0, &dpiX, &dpiY); factor = dpiY; }
return factor; }
LRESULT CMainFrame::OnDPIChanged(WPARAM wParam, LPARAM lParam) { int idpi = AnkhorGetDPI(this); double dpi = idpi / 96.0; if ( mMan->GetDisplayDPIFactor() != dpi ) { CRect rcNewScale(*(LPRECT)lParam);
TRC( L"DPI: %f\n", dpi );
LockWindowUpdate();
// No DPI Position change, when not yet opened if (IsWindowVisible()) { SetWindowPos( &wndTop, rcNewScale.left, rcNewScale.top, rcNewScale.Width(), rcNewScale.Height(), SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW); }
XTPDpiHelper()->Init(idpi); // ANKHOR GetCommandBars()->GetPaintManager()->RefreshMetrics();
RedrawAll(); UnlockWindowUpdate(); }
return TRUE; } void CXTPPaintManager::UpdateFonts() { CNonClientMetrics ncm; BYTE lfCharSet = XTPResourceManager()->GetFontCharset(); BOOL bUseClearType = m_bClearTypeTextQuality && XTPSystemVersion()->IsClearTypeTextQualitySupported();
if (m_bUseStandardFont) { CWindowDC dc(NULL); CLogFont lf; lf.lfHeight = ncm.lfMenuFont.lfHeight < 0 ? min(-XTP_COMMANDBAR_MIN_FONT_HEIGHT, ncm.lfMenuFont.lfHeight) : ncm.lfMenuFont.lfHeight; lf.lfWeight = ncm.lfMenuFont.lfWeight; lf.lfItalic = ncm.lfMenuFont.lfItalic; lf.lfCharSet = lfCharSet; lf.lfQuality = ncm.lfMenuFont.lfQuality; STRCPY_S(lf.lfFaceName, LF_FACESIZE, ncm.lfMenuFont.lfFaceName); if (bUseClearType) { lf.lfQuality = CLEARTYPE_QUALITY; }
if (0 < m_nFontHeight) { lf.lfHeight = -m_nFontHeight; }
lf.lfHeight = lf.lfHeight* XTPDpiHelper()->GetDPIY() / dc.GetDeviceCaps(LOGPIXELSY); // ANKHOR
m_nTextHeight = CalcTextHeight(lf.lfHeight, XTP_COMMANDBAR_TEXT_HEIGHT_FACTOR, XTP_DEFAULT_DISPLAY_DPI); m_nEditHeight = CalcCtrlHeight(lf.lfHeight, XTP_COMMANDBAR_CONTROL_HEIGHT_FACTOR, XTP_DEFAULT_DISPLAY_DPI); m_nSplitButtonDropDownWidth = CalcSplitButtonDropDownWidth(m_nTextHeight); m_nSplitButtonDropDownHeight = CalcSplitButtonDropDownHeight(lf.lfHeight);
SetCommandBarsFontIndirect(&lf, TRUE); }
LOGFONT lfIcon; VERIFY(CXTPDrawHelpers::GetIconLogFont(&lfIcon));
if (bUseClearType) { lfIcon.lfQuality = CLEARTYPE_QUALITY; ncm.lfSmCaptionFont.lfQuality = CLEARTYPE_QUALITY; ncm.lfStatusFont.lfQuality = CLEARTYPE_QUALITY; }
lfIcon.lfCharSet = lfCharSet; VERIFY(m_fontIcon.SetStandardFont(&lfIcon));
lfIcon.lfWeight = FW_BOLD; VERIFY(m_fontIconBold.SetStandardFont(&lfIcon));
ncm.lfSmCaptionFont.lfCharSet = lfCharSet; m_fontSmCaption.SetStandardFont(&ncm.lfSmCaptionFont);
ncm.lfStatusFont.lfCharSet = lfCharSet; m_fontToolTip.SetStandardFont(&ncm.lfStatusFont); }
// ANKHOR void CXTPDpi::Init(int dpi) { m_idpiX = dpi; m_idpiY = dpi;
for (int i = 0; i <= DpiValueCount; ++i) { m_nPositiveDpiValues.x = ScaleXInternal(i); m_nPositiveDpiValues.y = ScaleYInternal(i);
m_nNegativeDpiValues.x = ScaleXInternal(-i); m_nNegativeDpiValues.y = ScaleYInternal(-i); } }
|