在每个显示器模式下处理 DPI 缩放。这似乎适用于默认菜单栏和工具栏。
class CCustomMFCToolBar : public CMFCToolBar
{
public:
BOOL FullRestoreOriginalState()
{
// ensure restore original
if (m_uiOriginalResID == 0)
{
return FALSE;
}
// remove existing images
ResetAllImages();
// reset id so bitmaps are loaded again
UINT resid=m_uiOriginalResID;
m_uiOriginalResID=0;
// handle loading toolbar and bitmaps
BOOL bRes = LoadToolBar(resid);
AdjustLayout();
if (IsFloating())
{
RecalcLayout();
}
else if (m_pParentDockBar != NULL)
{
CSize sizeCurr = CalcFixedLayout(FALSE, IsHorizontal());
CRect rect;
GetWindowRect(rect);
if (rect.Size() != sizeCurr)
{
SetWindowPos(NULL, 0, 0, sizeCurr.cx, sizeCurr.cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
UpdateVirtualRect();
}
m_pDockBarRow->ArrangePanes(this);
AFXGetParentFrame(this)->RecalcLayout();
}
RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
return bRes;
}
};
在此处捕获 DPI 更改或重新启动所有项目,因为 WM_SETTINGCHANGED 在 WM_DPICHANGED 之后调用
void CMainFrame::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
{
CFrameWndEx::OnSettingChange(uFlags, lpszSection);
g_DPIHelper.SetChangedScaleForWindow(m_hWnd);
struct GlobalDataUnprotect : AFX_GLOBAL_DATA
{
#define AFX_FONT_NAME_OFFICE _T("Tahoma")
#define AFX_FONT_NAME_OFFICE_2007 _T("Segoe UI")
#define AFX_FONT_NAME_DEFAULT _T("MS Sans Serif")
#define AFX_FONT_NAME_VERT _T("Arial")
#define AFX_FONT_NAME_MARLETT _T("Marlett")
// This is a copy of UpdateFonts() modified a couple places to
// set the correct / changed scaling.
static int CALLBACK FontFamilyProcFonts(const LOGFONT FAR* lplf, const TEXTMETRIC FAR* lptm, ULONG ulFontType, LPARAM lParam)
{
ENSURE(lplf != NULL);
ENSURE(lParam != NULL);
CString strFont = lplf->lfFaceName;
return strFont.CollateNoCase((LPCTSTR) lParam) == 0 ? 0 : 1;
}
void UpdateScaledFonts()
{
CWindowDC dc(NULL);
m_dblRibbonImageScale = static_cast<double>(g_DPIHelper.GetScale())/100.0;
if (m_dblRibbonImageScale > 1. && m_dblRibbonImageScale < 1.1)
{
m_dblRibbonImageScale = 1.;
}
if (fontRegular.GetSafeHandle() != NULL)
{
::DeleteObject(fontRegular.Detach());
}
if (fontTooltip.GetSafeHandle() != NULL)
{
::DeleteObject(fontTooltip.Detach());
}
if (fontBold.GetSafeHandle() != NULL)
{
::DeleteObject(fontBold.Detach());
}
if (fontDefaultGUIBold.GetSafeHandle() != NULL)
{
::DeleteObject(fontDefaultGUIBold.Detach());
}
if (fontUnderline.GetSafeHandle() != NULL)
{
::DeleteObject(fontUnderline.Detach());
}
if (fontDefaultGUIUnderline.GetSafeHandle() != NULL)
{
::DeleteObject(fontDefaultGUIUnderline.Detach());
}
if (fontVert.GetSafeHandle() != NULL)
{
::DeleteObject(fontVert.Detach());
}
if (fontVertCaption.GetSafeHandle() != NULL)
{
::DeleteObject(fontVertCaption.Detach());
}
if (fontMarlett.GetSafeHandle() != NULL)
{
::DeleteObject(fontMarlett.Detach());
}
if (fontSmall.GetSafeHandle() != NULL)
{
::DeleteObject(fontSmall.Detach());
}
// Initialize fonts:
NONCLIENTMETRICS info;
info.cbSize = sizeof(info);
GetNonClientMetrics (info);
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
lf.lfCharSet = (BYTE) GetTextCharsetInfo(dc.GetSafeHdc(), NULL, 0);
lf.lfHeight = info.lfMenuFont.lfHeight;
lf.lfWeight = info.lfMenuFont.lfWeight;
lf.lfItalic = info.lfMenuFont.lfItalic;
//------------------
// Adjust font size:
//------------------
int nFontHeight = lf.lfHeight < 0 ? -lf.lfHeight : lf.lfHeight;
if (nFontHeight <= 12)
{
nFontHeight = 11;
}
else if (!m_bDontReduceFontHeight)
{
nFontHeight--;
}
lf.lfHeight = (lf.lfHeight < 0) ? -nFontHeight : nFontHeight;
lf.lfHeight=g_DPIHelper.ScaleNonClientMetricsFont(lf.lfHeight);
// Check if we should use system font
lstrcpy(lf.lfFaceName, info.lfMenuFont.lfFaceName);
BOOL fUseSystemFont = m_bUseSystemFont || (info.lfMenuFont.lfCharSet > SYMBOL_CHARSET);
if (!fUseSystemFont)
{
// Check for "Segoe UI" or "Tahoma" font existance:
if (::EnumFontFamilies(dc.GetSafeHdc(), NULL, FontFamilyProcFonts, (LPARAM)(LPCTSTR) AFX_FONT_NAME_OFFICE_2007) == 0)
{
// Found! Use MS Office 2007 font!
lstrcpy(lf.lfFaceName, AFX_FONT_NAME_OFFICE_2007);
lf.lfQuality=5; // CLEARTYPE_QUALITY;
}
else if (::EnumFontFamilies(dc.GetSafeHdc(), NULL, FontFamilyProcFonts, (LPARAM)(LPCTSTR) AFX_FONT_NAME_OFFICE) == 0)
{
// Found! Use MS Office font!
lstrcpy(lf.lfFaceName, AFX_FONT_NAME_OFFICE);
}
else
{
// Not found. Use default font:
lstrcpy(lf.lfFaceName, AFX_FONT_NAME_DEFAULT);
}
}
fontRegular.CreateFontIndirect(&lf);
// Create small font:
LONG lfHeightSaved = lf.lfHeight;
lf.lfHeight = (long)((1. + abs(lf.lfHeight)) * 2 / 3);
if (lfHeightSaved < 0)
{
lf.lfHeight = -lf.lfHeight;
}
fontSmall.CreateFontIndirect(&lf);
lf.lfHeight = lfHeightSaved;
// Create tooltip font:
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(ncm);
GetNonClientMetrics (ncm);
lf.lfItalic = ncm.lfStatusFont.lfItalic;
lf.lfWeight = ncm.lfStatusFont.lfWeight;
fontTooltip.CreateFontIndirect(&lf);
lf.lfItalic = info.lfMenuFont.lfItalic;
lf.lfWeight = info.lfMenuFont.lfWeight;
// Create "underline" font:
lf.lfUnderline = TRUE;
fontUnderline.CreateFontIndirect(&lf);
lf.lfUnderline = FALSE;
// Create bold font:
lf.lfWeight = FW_BOLD;
fontBold.CreateFontIndirect(&lf);
// Create Marlett font:
BYTE bCharSet = lf.lfCharSet;
lf.lfWeight = info.lfMenuFont.lfWeight;
lf.lfCharSet = SYMBOL_CHARSET;
lf.lfWeight = 0;
lf.lfHeight=g_DPIHelper.ScaleNonClientMetricsFont(::GetSystemMetrics(SM_CYMENUCHECK) - 1);
lstrcpy(lf.lfFaceName, AFX_FONT_NAME_MARLETT);
fontMarlett.CreateFontIndirect(&lf);
lf.lfCharSet = bCharSet; // Restore charset
// Create vertical font:
CFont font;
if (font.CreateStockObject(DEFAULT_GUI_FONT))
{
if (font.GetLogFont(&lf) != 0)
{
lf.lfOrientation = 900;
lf.lfEscapement = 2700;
lf.lfHeight = g_DPIHelper.ScaleNonClientMetricsFont(info.lfMenuFont.lfHeight);
lf.lfWeight = info.lfMenuFont.lfWeight;
lf.lfItalic = info.lfMenuFont.lfItalic;
{
lstrcpy(lf.lfFaceName, AFX_FONT_NAME_VERT);
}
fontVert.CreateFontIndirect(&lf);
lf.lfEscapement = 900;
fontVertCaption.CreateFontIndirect(&lf);
}
}
// Create dialog underline and bold fonts:
CFont* pDefaultGUIFont = CFont::FromHandle((HFONT) GetStockObject(DEFAULT_GUI_FONT));
ASSERT_VALID(pDefaultGUIFont);
pDefaultGUIFont->GetLogFont(&lf);
lf.lfUnderline = TRUE;
fontDefaultGUIUnderline.CreateFontIndirect(&lf);
lf.lfUnderline = FALSE;
lf.lfWeight = FW_BOLD;
fontDefaultGUIBold.CreateFontIndirect(&lf);
UpdateTextMetrics();
extern CObList afxAllToolBars;
// Notify toolbars about font changing:
for (POSITION posTlb = afxAllToolBars.GetHeadPosition(); posTlb != NULL;)
{
CMFCToolBar* pToolBar = (CMFCToolBar*) afxAllToolBars.GetNext(posTlb);
ENSURE(pToolBar != NULL);
if (CWnd::FromHandlePermanent(pToolBar->m_hWnd) != NULL)
{
ASSERT_VALID(pToolBar);
pToolBar->OnGlobalFontsChanged();
}
}
}
};
GlobalDataUnprotect *globaldata=reinterpret_cast<GlobalDataUnprotect*>(GetGlobalData());
globaldata->UpdateScaledFonts();
m_wndToolBar.CleanUpLockedImages();
m_wndToolBar.FullRestoreOriginalState();
}