Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Dynamically creating CFont to fit in CRect area??

Posted on 2002-05-04
8
Medium Priority
?
347 Views
Last Modified: 2013-11-20
What is the best way to resize a CFont to fit in a given area of my Custom Control?  The cx and cy of the control both change and have to be taken into account.  I guess the best way to explain, is using a CRect, I want my text to scale so it always fits in the CRect; top to bottom, left to right.  I know how to tie the CFont height variable to  CRect.Height() but I also need to take into accont the Width().  Anyway... There must be an easy way to accomplish my goal that I am not seeing.  All suggestions welcome and code samples greatly appreciated.

-Michael
0
Comment
Question by:Surfer
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
8 Comments
 
LVL 16

Expert Comment

by:AlexNek
ID: 6989991
2 Surfer
AFAIK it is not possible to "fill exact" any rectangle with font. But for kerning emulation you can try to use char by char output. Or try to use RichEdit from V2.0
0
 
LVL 86

Expert Comment

by:jkr
ID: 6989993
You could check the actual size of the text you want to place in the rect using 'GetTextExtentPoint32()' - however, I am not aware that there is a more comfortable "other way round"...
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6990707
This code seems to work.  All it does is keep trying smaller and smaller versions of the font until the text fits.  So you can easily end up with a font that is too 'short' just so that its width fits in the box.  There is *no* command that will produce a 'tall,skinny' font from a regular font to handle that situation.  

(However, one idea would be to print tht text to the DC, capture a bitmap of it, then use StretchDIBits to generate one that was 'just right' then display that bitmap -- instead of the actual text.

IMPORTANT: You will need to add some error checking to the code below; it can easily get into an infinte loop.
During testing, I found that the font was staying the same size because the parent dialog's font was MS Sans Serif -- a non TrueType font.  

I am having to release the DC becasue I was working with a EDIT window which as the CS_PARENTDC  class bit.

CFont gcFont;

void CD03Dlg::OnButton1()
{
     CString   sText;
     LOGFONT   rLF;
     CRect     rc;
     CSize     cSz;

     m_ctlEdit.GetWindowText( sText );

     CFont* pFont= m_ctlEdit.GetFont();
     pFont->GetLogFont( &rLF );
     
     m_ctlEdit.GetWindowRect( &rc );

     CDC*   pDC=      m_ctlEdit.GetDC();
     CFont* pOldFont= pDC->SelectObject( pFont );

     while ( 1 ) {
          cSz=  pDC->GetTextExtent( sText );
          if ( cSz.cx <= rc.Width() && cSz.cy <= rc.Height() ) {
               pDC->SelectObject( pOldFont );
               break;
          }
          rLF.lfHeight += (rLF.lfHeight > 0 ? -1: 1);
          gcFont.DeleteObject();
          BOOL fRet= gcFont.CreateFontIndirect( &rLF );

          pDC->SelectObject( &gcFont );
     }
     pDC->SelectObject( pOldFont );
     m_ctlEdit.ReleaseDC( pDC );
     
     m_ctlEdit.SetFont( &gcFont, TRUE );
     m_ctlEdit.Invalidate();
}

0
Migrating Your Company's PCs

To keep pace with competitors, businesses must keep employees productive, and that means providing them with the latest technology. This document provides the tips and tricks you need to help you migrate an outdated PC fleet to new desktops, laptops, and tablets.

 

Author Comment

by:Surfer
ID: 6991689
(However, one idea would be to print tht text to the DC, capture a bitmap of it, then use StretchDIBits
to generate one that was 'just right' then display that bitmap -- instead of the actual text.

This sounds interesting.  Can you please give me a code sample?

-Michael
0
 

Author Comment

by:Surfer
ID: 6991693
(However, one idea would be to print tht text to the DC, capture a bitmap of it, then use StretchDIBits
to generate one that was 'just right' then display that bitmap -- instead of the actual text.

This sounds interesting.  Can you please give me a code sample?

-Michael
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6992384
This works beautifully.  I've outfdone myself here!
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

BOOL TextToBitmap(  LPCSTR szText, CFont* pcFont, CRect* prcDest, CBitmap* pcBmpDest )
{
     CBitmap     cBmpCanvas;
     CWindowDC     dcWin( AfxGetMainWnd() );
     CDC           memSrcDC;
     CDC           memDestDC;

     pcBmpDest->DeleteObject();
     
     memSrcDC.CreateCompatibleDC( &dcWin );

     CFont*   pOldFont=      memSrcDC.SelectObject( pcFont );

     CSize cszSrc= memSrcDC.GetTextExtent( szText, strlen(szText) );

     cBmpCanvas.CreateCompatibleBitmap( &dcWin, cszSrc.cx, cszSrc.cy );

     CBitmap* pOldSrcBitmap= memSrcDC.SelectObject( &cBmpCanvas );

     CRect rcCanvas( CPoint(0,0), cszSrc );
     BOOL fRet= memSrcDC.ExtTextOut( 0,0, ETO_OPAQUE, &rcCanvas, szText, strlen(szText), 0 );

     //------------- now bmpCanvas has the 'raw' image
     //------------- stretch that to fit desired rectangle

     memDestDC.CreateCompatibleDC( &dcWin );

     pcBmpDest->CreateCompatibleBitmap( &dcWin, prcDest->Width(), prcDest->Height() );
     CBitmap* pOldDestBitmap= memDestDC.SelectObject( pcBmpDest );

     memDestDC.SetStretchBltMode( HALFTONE ); // looks good!
     memDestDC.SetBrushOrg(0,0);
     
     memDestDC.StretchBlt(
          0,0, prcDest->Width(), prcDest->Height(),
          &memSrcDC,
          0,0,  cszSrc.cx,cszSrc.cy,
          SRCCOPY
     );

     memSrcDC.SelectObject( pOldSrcBitmap );
     memSrcDC.SelectObject( pOldFont );

     memDestDC.SelectObject( pOldDestBitmap );

     return( TRUE );
}

//--------------------------------- example test
// it takes test fome an edit box, generates a bitmap, and sets it into a CStatic.

void CD03Dlg::OnButton1()
{
     CRect rcDest(   0,0, 100, 20 );

     static CBitmap cBmp; // must persist so that SetBitmap, below won't croak

     CFont cFont;
     cFont.CreatePointFont( 120, "Arial" );

     CString sText;
     GetDlgItemText( IDC_EDIT1, sText );

     BOOL fRet= TextToBitmap( sText, &cFont,  &rcDest, &cBmp );

     m_ctlBmpDisplay.SetBitmap( (HBITMAP)cBmp.m_hObject );
}
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 800 total points
ID: 7007777
Hey Surfer,
I worked a LONG TIME to create that perfect solution for you.  Why have you not responded?

-- Dan
0
 

Author Comment

by:Surfer
ID: 7007784
Because I have been EXTREMELY busy working on a couple other projects.  Your solution was indeed a very elegant approach that I think will do the trick.  Thanks for your time and patients!
0

Featured Post

Learn how to optimize MySQL for your business need

With the increasing importance of apps & networks in both business & personal interconnections, perfor. has become one of the key metrics of successful communication. This ebook is a hands-on business-case-driven guide to understanding MySQL query parameter tuning & database perf

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

How to update Firmware and Bios in Dell Equalogic PS6000 Arrays and Hard Disks firmware update.
Microsoft will be releasing the Windows 10 Creators Update in just a matter of weeks. Are you prepared? Follow these steps to ensure everything goes smoothly and you don't lose valuable data on your PC.
This tutorial will walk an individual through configuring a drive on a Windows Server 2008 to perform shadow copies in order to quickly recover deleted files and folders. Click on Start and then select Computer to view the available drives on the se…
This tutorial will walk an individual through the process of configuring basic necessities in order to use the 2010 version of Data Protection Manager. These include storage, agents, and protection jobs. Launch Data Protection Manager from the deskt…

688 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question