【问题标题】:Changing the font background so the text can be seen更改字体背景以便可以看到文本
【发布时间】:2017-03-06 19:15:39
【问题描述】:

我的应用程序中有一些代码可以选择字体。它直观地显示了当前字体的示例:

代码在这里:

void CExportSettingsDlg::OnPaint()
{
    CPaintDC    dc( this ); // device context for painting

    // This will draw the sample text for us using the current font
    DrawSampleText( &dc );

    // Do not call CDialog::OnPaint() for painting messages
}

void CExportSettingsDlg::DrawSampleText(CDC *pDC)
{
    CDC         dcMem;
    CPen        *pOldPen;
    CBrush      *pOldBrush;
    CBitmap     *pBmpOld;
    CFont       *pOldFont, fntSample;
    LOGFONT     lfSampleFont;
    int         nFontHeightPixels, iBackModeOld;
    COLORREF    crTextColourOld;
    CString     strSample;

    ASSERT( pDC != NULL );
    ASSERT( m_plfCurrentFont != NULL );
    if( pDC != NULL && m_plfCurrentFont != NULL )
    {
        strSample.LoadString( IDS_STR_SAMPLE );

        dcMem.CreateCompatibleDC( NULL );

        // Select our gdi stuff into dc
        pBmpOld = (CBitmap*)dcMem.SelectObject( &m_bmpSample );
        pOldPen = (CPen*)dcMem.SelectStockObject( BLACK_PEN );
        pOldBrush = (CBrush*)dcMem.SelectStockObject( WHITE_BRUSH );

        // Create the font
        fntSample.CreateFontIndirect( m_plfCurrentFont );

        // Get it back out so that we can adjust the font size correctly
        fntSample.GetLogFont( &lfSampleFont );

        // Font height in pixels
        nFontHeightPixels = theApp.GetFontHeightPixels(lfSampleFont.lfHeight, &dcMem);

        // Update font
        lfSampleFont.lfHeight = nFontHeightPixels;
        fntSample.DeleteObject();
        fntSample.CreateFontIndirect( &lfSampleFont );

        // Erase display  (will draw white rectangle with black border)
        dcMem.Rectangle( m_rctSampleMem );

        // Select our font and colour values and modes
        pOldFont = (CFont*)dcMem.SelectObject( &fntSample );
        crTextColourOld = dcMem.SetTextColor( m_crCurrentFontColour );
        iBackModeOld = dcMem.SetBkMode( TRANSPARENT );

        // Display the text
        dcMem.DrawText( strSample, m_rctSampleText, DT_SINGLELINE|DT_VCENTER|DT_CENTER );

        // Blast main memory dc to display
        pDC->BitBlt( m_rctSample.left, m_rctSample.top,
            m_rctSample.Width(), m_rctSample.Height(),
            &dcMem, 0, 0, SRCCOPY );

        // Restore old font and colour values and modes
        dcMem.SelectObject( pOldFont );
        dcMem.SetTextColor( crTextColourOld );
        dcMem.SetBkMode( iBackModeOld );
        dcMem.SelectObject( pBmpOld );
        dcMem.SelectObject( pOldPen );
        dcMem.SelectObject( pOldBrush );

        // Release memory
        dcMem.DeleteDC();
        fntSample.DeleteObject();
        // brushes and pens don't need deleting as they are stock objects
    }
}

现在,我有其他代码显示标准 CFontDialog,用户还可以在其中设置字体颜色:

如您所见,在此对话框中,它使用透明背景作为字体示例,因此显示白色文本。但公平地说,由于我使用的蒙皮,它显示得更多。

在我的窗口上,我使用的是白色背景。所以你看到了我的问题。仅此而已。你看不到。 :)

没有变得复杂,并且考虑到我是色盲(红色/绿色)的事实,我们可以使用一种简单的技术来始终确保 my 示例中的示例背景始终适合给定正在渲染的字体颜色?

谢谢。

【问题讨论】:

  • 可能相关:Formula to determine brightness of RGB color。使用白色背景,只要字体亮度在下半部分,从 0.5 开始切换到黑色背景。我相信 Windows 使用类似的方案来决定桌面快捷方式项目文本的颜色。
  • @IInspectable 这个问题有很多答案,其中大部分都超出了我的想象。我理解你所描述的,但是哪个答案可以做到这一点?
  • 接受答案的所有公式都可以使用。我可能会选择第一个或第二个,因为它们更容易计算。它们采用 RGB 值(您的字体颜色)并计算 [0 .. 1] 范围内的单个亮度值(0 为暗,1 为亮)。使用该值来决定背景:从 [0 .. 0.5) 的值使用明亮的背景,从 [0.5 .. 1] 的值使用深色背景。
  • 假设您不处理透明度,您是否考虑过使用与前景色按位相反的 RGB 颜色作为背景?它可以制作一些生动的背景。
  • 假设 rgbfg 是前景色。 DWORD rgbbg = (~rgbfg) & 0x00ffffff;或多或少...

标签: fonts colors mfc


【解决方案1】:

根据将我引向另一个问题的 cmets,我能够解决此问题:

void CExportSettingsDlg::DrawSampleText(CDC *pDC)
{
    CDC         dcMem;
    CPen        *pOldPen;
    CBrush      *pOldBrush;
    CBitmap     *pBmpOld;
    CFont       *pOldFont, fntSample;
    LOGFONT     lfSampleFont;
    int         nFontHeightPixels, iBackModeOld;
    COLORREF    crTextColourOld;
    CString     strSample;

    ASSERT( pDC != NULL );
    ASSERT( m_plfCurrentFont != NULL );
    if( pDC != NULL && m_plfCurrentFont != NULL )
    {
        strSample.LoadString( IDS_STR_SAMPLE );

        dcMem.CreateCompatibleDC( NULL );

        // Select our gdi stuff into dc
        pBmpOld = (CBitmap*)dcMem.SelectObject( &m_bmpSample );
        pOldPen = (CPen*)dcMem.SelectStockObject( BLACK_PEN );
        //pOldBrush = (CBrush*)dcMem.SelectStockObject( WHITE_BRUSH );
        CBrush brBackground;
        double dLumi = (0.2126 * GetRValue(m_crCurrentFontColour))
            + (0.7152*GetGValue(m_crCurrentFontColour)) + (0.0722*GetBValue(m_crCurrentFontColour));
        if (dLumi <= 0.5)
            brBackground.CreateSolidBrush(PALETTERGB(255, 255, 255));
        else
            brBackground.CreateSolidBrush(PALETTERGB(0, 0, 0));
        pOldBrush = (CBrush*)dcMem.SelectObject(&brBackground);

        // Create the font
        fntSample.CreateFontIndirect( m_plfCurrentFont );

        // Get it back out so that we can adjust the font size correctly
        fntSample.GetLogFont( &lfSampleFont );

        // Font height in pixels
        nFontHeightPixels = theApp.GetFontHeightPixels(lfSampleFont.lfHeight, &dcMem);

        // Update font
        lfSampleFont.lfHeight = nFontHeightPixels;
        fntSample.DeleteObject();
        fntSample.CreateFontIndirect( &lfSampleFont );

        // Erase display  (will draw  a white rectangle with black border)
        dcMem.Rectangle( m_rctSampleMem );

        // Select our font and colour values and modes
        pOldFont = (CFont*)dcMem.SelectObject( &fntSample );
        crTextColourOld = dcMem.SetTextColor( m_crCurrentFontColour );
        iBackModeOld = dcMem.SetBkMode( TRANSPARENT );

        // Display the text
        dcMem.DrawText( strSample, m_rctSampleText, DT_SINGLELINE|DT_VCENTER|DT_CENTER );

        // Blast main memory dc to display
        pDC->BitBlt( m_rctSample.left, m_rctSample.top,
            m_rctSample.Width(), m_rctSample.Height(),
            &dcMem, 0, 0, SRCCOPY );

        // Restore old font and colour values and modes
        dcMem.SelectObject( pOldFont );
        dcMem.SetTextColor( crTextColourOld );
        dcMem.SetBkMode( iBackModeOld );
        dcMem.SelectObject( pBmpOld );
        dcMem.SelectObject( pOldPen );
        dcMem.SelectObject( pOldBrush );

        // Release memory
        dcMem.DeleteDC();
        fntSample.DeleteObject();
        // brushes and pens don't need deleting as they are stock objects
        brBackground.DeleteObject();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-15
    • 1970-01-01
    • 2020-11-05
    • 2021-05-31
    • 2021-05-03
    • 2020-05-03
    • 2016-07-19
    • 1970-01-01
    相关资源
    最近更新 更多