home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / PPGFONT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  27.2 KB  |  1,106 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1997 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFXCTL_PAGE_SEG
  14. #pragma code_seg(AFXCTL_PAGE_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CFontPropPage implementation
  26.  
  27. BEGIN_MESSAGE_MAP(CFontPropPage, CStockPropPage)
  28.     //{{AFX_MSG_MAP(CFontPropPage)
  29.     ON_WM_PAINT()
  30.     ON_CBN_SELCHANGE(AFX_IDC_FONTPROP, OnSelchangeFontprop)
  31.     ON_CBN_EDITUPDATE(AFX_IDC_FONTNAMES, OnEditupdateFontnames)
  32.     ON_CBN_EDITUPDATE(AFX_IDC_FONTSIZES, OnEditupdateFontsizes)
  33.     ON_CBN_SELCHANGE(AFX_IDC_FONTNAMES, OnSelchangeFontnames)
  34.     ON_CBN_SELCHANGE(AFX_IDC_FONTSIZES, OnSelchangeFontsizes)
  35.     ON_CBN_SELCHANGE(AFX_IDC_FONTSTYLES, OnSelchangeFontstyles)
  36.     ON_CBN_EDITCHANGE(AFX_IDC_FONTSTYLES, OnEditchangeFontstyles)
  37.     ON_BN_CLICKED(AFX_IDC_STRIKEOUT, OnStrikeout)
  38.     ON_BN_CLICKED(AFX_IDC_UNDERLINE, OnUnderline)
  39.     //}}AFX_MSG_MAP
  40. END_MESSAGE_MAP()
  41.  
  42. CFontPropPage::CFontPropPage() :
  43.     CStockPropPage(IDD, AFX_IDS_FONT_PPG_CAPTION)
  44. {
  45.     //{{AFX_DATA_INIT(CFontPropPage)
  46.     //}}AFX_DATA_INIT
  47. }
  48.  
  49. BOOL _AfxStringFromCy(CString& str, CY& cy)
  50. {
  51.     VARIANTARG varCy;
  52.     VARIANTARG varBstr;
  53.     AfxVariantInit(&varCy);
  54.     AfxVariantInit(&varBstr);
  55.     V_VT(&varCy) = VT_CY;
  56.     V_CY(&varCy) = cy;
  57.     if (FAILED(VariantChangeType(&varBstr, &varCy, 0, VT_BSTR)))
  58.     {
  59.         VariantClear(&varCy);
  60.         VariantClear(&varBstr);
  61.         return FALSE;
  62.     }
  63.     str = V_BSTR(&varBstr);
  64.     VariantClear(&varCy);
  65.     VariantClear(&varBstr);
  66.     return TRUE;
  67. }
  68.  
  69. BOOL _AfxCyFromString(CY& cy, LPCTSTR psz)
  70. {
  71.     USES_CONVERSION;
  72.  
  73.     VARIANTARG varBstr;
  74.     VARIANTARG varCy;
  75.     AfxVariantInit(&varBstr);
  76.     AfxVariantInit(&varCy);
  77.     V_VT(&varBstr) = VT_BSTR;
  78.     V_BSTR(&varBstr) = SysAllocString(T2COLE(psz));
  79.     if (FAILED(VariantChangeType(&varCy, &varBstr, 0, VT_CY)))
  80.     {
  81.         VariantClear(&varBstr);
  82.         VariantClear(&varCy);
  83.         return FALSE;
  84.     }
  85.     cy = V_CY(&varCy);
  86.     VariantClear(&varBstr);
  87.     VariantClear(&varCy);
  88.     return TRUE;
  89. }
  90.  
  91. #define DSx     0x00660046L
  92. #define DSna    0x00220326L
  93.  
  94. void _AfxDrawMaskedBitmap(CDC* pDC, CBitmap* pbmp, CBitmap* pbmpMask,
  95.     int x, int y, int cx, int cy)
  96. {
  97.     COLORREF oldBkColor = pDC->SetBkColor(RGB(255, 255, 255));
  98.     COLORREF oldTextColor = pDC->SetTextColor(RGB(0, 0, 0));
  99.  
  100.     CDC dcCompat;
  101.     dcCompat.CreateCompatibleDC(pDC);
  102.     CBitmap* pbmpSave = dcCompat.SelectObject(pbmp);
  103.     pDC->BitBlt(x, y, cx, cy, &dcCompat, 0, 0, DSx);
  104.     dcCompat.SelectObject(pbmpMask);
  105.     pDC->BitBlt(x, y, cx, cy, &dcCompat, 0, 0, DSna);
  106.     dcCompat.SelectObject(pbmp);
  107.     pDC->BitBlt(x, y, cx, cy, &dcCompat, 0, 0, DSx);
  108.     dcCompat.SelectObject(pbmpSave);
  109.  
  110.     pDC->SetBkColor(oldBkColor);
  111.     pDC->SetTextColor(oldTextColor);
  112. }
  113.  
  114. void _AfxInitMaskFromBitmap(CBitmap* pbmp, CBitmap* pbmpMask)
  115. {
  116.     BITMAP bmp;
  117.     pbmp->GetObject(sizeof (BITMAP), &bmp);
  118.     pbmpMask->CreateBitmap(bmp.bmWidth, bmp.bmHeight, 1, 1, NULL);
  119.  
  120.     CDC dcDst;
  121.     dcDst.CreateCompatibleDC(NULL);
  122.     CDC dcSrc;
  123.     dcSrc.CreateCompatibleDC(NULL);
  124.     CBitmap* pbmpSaveDst = dcDst.SelectObject(pbmpMask);
  125.     CBitmap* pbmpSaveSrc = dcSrc.SelectObject(pbmp);
  126.  
  127.     COLORREF oldBkColor = dcSrc.SetBkColor(dcSrc.GetPixel(0, 0));
  128.     dcDst.BitBlt(0, 0, bmp.bmWidth, bmp.bmHeight, &dcSrc, 0, 0, NOTSRCCOPY);
  129.     dcSrc.SetBkColor(oldBkColor);
  130. }
  131.  
  132. void CFontPropPage::DoDataExchange(CDataExchange* pDX)
  133. {
  134.     //{{AFX_DATA_MAP(CFontPropPage)
  135.     DDX_Control(pDX, AFX_IDC_FONTPROP, m_FontProp);
  136.     DDX_Control(pDX, AFX_IDC_SAMPLEBOX, m_SampleBox);
  137.     DDX_Control(pDX, AFX_IDC_FONTSTYLES, m_FontStyles);
  138.     DDX_Control(pDX, AFX_IDC_FONTSIZES, m_FontSizes);
  139.     DDX_Control(pDX, AFX_IDC_FONTNAMES, m_FontNames);
  140.     //}}AFX_DATA_MAP
  141.  
  142.     if (pDX->m_bSaveAndValidate)
  143.     {
  144.         FONTOBJECT fobj;
  145.         fobj.strName = m_FontNames.GetCurrentName();
  146.  
  147.         if (fobj.strName.IsEmpty())
  148.             return;
  149.  
  150.         m_FontSizes.GetPointSize(fobj.cySize);
  151.  
  152.         if (m_nCurrentStyle & NTM_REGULAR)
  153.             fobj.sWeight = FW_REGULAR;
  154.         if (m_nCurrentStyle & NTM_BOLD)
  155.         {
  156.             fobj.sWeight = FW_BOLD;
  157.             fobj.bBold = TRUE;
  158.         }
  159.         else
  160.             fobj.bBold = FALSE;
  161.         if (m_nCurrentStyle & NTM_ITALIC)
  162.             fobj.bItalic = TRUE;
  163.         else
  164.             fobj.bItalic = FALSE;
  165.         fobj.bUnderline = m_bUnderline;
  166.         fobj.bStrikethrough = m_bStrikeOut;
  167.  
  168.         SetFontProps(pDX, fobj, m_strPropName);
  169.     }
  170.     else
  171.     {
  172.         FONTOBJECT fobj;
  173.         MERGEOBJECT mobj;
  174.         if (!m_strPropName.IsEmpty() && GetFontProps(pDX, &fobj, m_strPropName, &mobj))
  175.         {
  176.             if (fobj.bBold && fobj.bItalic)
  177.                 m_nCurrentStyle = NTM_BOLD | NTM_ITALIC;
  178.             else if (fobj.bBold)
  179.                 m_nCurrentStyle = NTM_BOLD;
  180.             else if (fobj.bItalic)
  181.                 m_nCurrentStyle = NTM_ITALIC;
  182.             else
  183.                 m_nCurrentStyle = NTM_REGULAR;
  184.             m_nActualStyle = m_nCurrentStyle;
  185.             m_bUnderline = fobj.bUnderline;
  186.             m_bStrikeOut = fobj.bStrikethrough;
  187.  
  188.             mobj.bNameOK = TRUE;
  189.             mobj.bSizeOK = TRUE;
  190.             mobj.bStyleOK = TRUE;
  191.             mobj.bUnderlineOK = TRUE;
  192.             mobj.bStrikethroughOK = TRUE;
  193.  
  194.             _AfxStringFromCy(m_strFontSize, fobj.cySize);
  195.             SelectFontFromList(fobj.strName, &mobj);
  196.         }
  197.     }
  198. }
  199.  
  200. BOOL CFontPropPage::SetFontProps(CDataExchange* pDX, FONTOBJECT fobj, LPCTSTR pszPropName)
  201. {
  202.     USES_CONVERSION;
  203.  
  204.     BOOL bStatus = FALSE;
  205.     COleDispatchDriver PropDispDriver;
  206.  
  207.     // Set the properties for all the objects
  208.     ASSERT_KINDOF(COlePropertyPage, pDX->m_pDlgWnd);
  209.     COlePropertyPage* propDialog = (COlePropertyPage*)(pDX->m_pDlgWnd);
  210.  
  211.     ULONG nObjects;
  212.     LPDISPATCH* ppDisp = GetObjectArray(&nObjects);
  213.  
  214.     for (ULONG i = 0; i < nObjects; i++)
  215.     {
  216.         DISPID dwDispID;
  217.  
  218.         // Get the Dispatch ID for the property and if successful set the value
  219.         LPCOLESTR lpOleStr = T2COLE(pszPropName);
  220.         if (SUCCEEDED(ppDisp[i]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr,
  221.             1, m_lcid, &dwDispID)))
  222.         {
  223.             LPDISPATCH pFontDisp = NULL;
  224.  
  225.             // Get property
  226.             PropDispDriver.AttachDispatch(ppDisp[i], FALSE);
  227.             TRY
  228.                 PropDispDriver.GetProperty(dwDispID, VT_DISPATCH, &pFontDisp);
  229.             END_TRY
  230.             PropDispDriver.DetachDispatch();
  231.  
  232.             if (pFontDisp == NULL)
  233.                 continue;
  234.  
  235.             // Get font interface
  236.             IFont * pFont;
  237.             HRESULT hresult = pFontDisp->QueryInterface(IID_IFont, (void**)&pFont);
  238.             if (hresult == S_OK)
  239.             {
  240.                 // Set font characteristics
  241.                 if (propDialog->GetControlStatus(AFX_IDC_FONTNAMES))
  242.                 {
  243.                     BSTR bstrName = fobj.strName.AllocSysString();
  244.                     pFont->put_Name(bstrName);
  245.                     SysFreeString(bstrName);
  246.                 }
  247.                 if (propDialog->GetControlStatus(AFX_IDC_FONTSIZES))
  248.                     pFont->put_Size(fobj.cySize);
  249.                 if (propDialog->GetControlStatus(AFX_IDC_FONTSTYLES))
  250.                 {
  251.                     pFont->put_Bold(fobj.bBold);
  252.                     pFont->put_Italic(fobj.bItalic);
  253.                     pFont->put_Weight(fobj.sWeight);
  254.                 }
  255.                 if (propDialog->GetControlStatus(AFX_IDC_UNDERLINE))
  256.                     pFont->put_Underline(fobj.bUnderline);
  257.                 if (propDialog->GetControlStatus(AFX_IDC_STRIKEOUT))
  258.                     pFont->put_Strikethrough(fobj.bStrikethrough);
  259.  
  260.                 // Release the font interface
  261.                 RELEASE(pFont);
  262.                 bStatus = TRUE;
  263.             }
  264.  
  265.             // Release the font dispatch interface
  266.             RELEASE(pFontDisp);
  267.         }
  268.     }
  269.     return bStatus;
  270. }
  271.  
  272. BOOL CFontPropPage::GetFontProps(CDataExchange* pDX, FONTOBJECT* pfobj, LPCTSTR pszPropName, MERGEOBJECT* pmobj)
  273. {
  274.     USES_CONVERSION;
  275.     BOOL bStatus = FALSE;
  276.  
  277.     COleDispatchDriver PropDispDriver;
  278.  
  279.     // Set the properties for all the objects
  280.     ASSERT_KINDOF(COlePropertyPage, pDX->m_pDlgWnd);
  281.     COlePropertyPage* propDialog = (COlePropertyPage*)(pDX->m_pDlgWnd);
  282.  
  283.     ULONG nObjects;
  284.     LPDISPATCH* ppDisp = GetObjectArray(&nObjects);
  285.  
  286.     for (ULONG i = 0; i < nObjects; i++)
  287.     {
  288.         DISPID dwDispID;
  289.  
  290.         // Get the Dispatch ID for the property and if successful get the value
  291.         LPCOLESTR lpOleStr = T2COLE(pszPropName);
  292.         if (SUCCEEDED(ppDisp[i]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr,
  293.             1, m_lcid, &dwDispID)))
  294.         {
  295.             LPDISPATCH pFontDisp;
  296.  
  297.             // Get property
  298.             PropDispDriver.AttachDispatch(ppDisp[i], FALSE);
  299.             PropDispDriver.GetProperty(dwDispID, VT_DISPATCH, &pFontDisp);
  300.             PropDispDriver.DetachDispatch();
  301.  
  302.             if (pFontDisp == NULL)
  303.                 continue;
  304.  
  305.             // Get font interface
  306.             IFont * pFont;
  307.             HRESULT hresult = pFontDisp->QueryInterface(IID_IFont, (void**)&pFont);
  308.             if (hresult == S_OK)
  309.             {
  310.                 BOOL bTemp;
  311.  
  312.                 // Set font characteristics
  313.                 OLECHAR *pszName;
  314.                 pFont->get_Name(&pszName);
  315.                 if (_tcscmp(OLE2CT(pszName), pfobj->strName) != 0 && i != 0)
  316.                     pmobj->bNameOK = FALSE;
  317.                 pfobj->strName = pszName;
  318.                 SysFreeString(pszName);
  319.  
  320.                 CY cyTemp;
  321.                 pFont->get_Size(&cyTemp);
  322.                 if ((cyTemp.Lo != pfobj->cySize.Lo || cyTemp.Hi != pfobj->cySize.Hi) && i != 0)
  323.                     pmobj->bSizeOK = FALSE;
  324.                 pfobj->cySize = cyTemp;
  325.  
  326.                 pFont->get_Bold(&bTemp);
  327.                 if (pfobj->bBold != bTemp && i != 0)
  328.                     pmobj->bStyleOK = FALSE;
  329.                 pfobj->bBold = bTemp;
  330.  
  331.                 pFont->get_Italic(&bTemp);
  332.                 if (pfobj->bItalic != bTemp && i != 0)
  333.                     pmobj->bStyleOK = FALSE;
  334.                 pfobj->bItalic = bTemp;
  335.  
  336.                 pFont->get_Underline(&bTemp);
  337.                 if (pfobj->bUnderline != bTemp && i != 0)
  338.                     pmobj->bUnderlineOK = FALSE;
  339.                 pfobj->bUnderline = bTemp;
  340.  
  341.                 pFont->get_Strikethrough(&bTemp);
  342.                 if (pfobj->bStrikethrough != bTemp && i != 0)
  343.                     pmobj->bStrikethroughOK = FALSE;
  344.                 pfobj->bStrikethrough = bTemp;
  345.  
  346.                 short sTemp;
  347.  
  348.                 pFont->get_Weight(&sTemp);
  349.                 if (pfobj->sWeight != sTemp && i != 0)
  350.                     pmobj->bStyleOK = FALSE;
  351.                 pfobj->sWeight = sTemp;
  352.  
  353.                 // Release the font interface
  354.                 RELEASE(pFont);
  355.                 bStatus = TRUE;
  356.             }
  357.  
  358.             // Release font interface
  359.             RELEASE(pFontDisp);
  360.         }
  361.     }
  362.     return bStatus;
  363. }
  364.  
  365. BOOL CFontPropPage::OnInitDialog()
  366. {
  367.     CStockPropPage::OnInitDialog();
  368.     OnObjectsChanged();
  369.     IgnoreApply(AFX_IDC_FONTPROP);
  370.  
  371.     return TRUE;  // return TRUE  unless you set the focus to a control
  372. }
  373.  
  374. void CFontPropPage::FillFacenameList()
  375. {
  376.     // Clear the list
  377.     m_FontNames.ResetContent();
  378.  
  379.     // Create a DC to enumerate
  380.     CClientDC dc(NULL);
  381. #ifndef _MAC
  382.     EnumFontFamilies(dc.GetSafeHdc(), (LPCTSTR) NULL, (FONTENUMPROC) CFontPropPage::EnumFontFamiliesCallBack, (LPARAM) this);
  383. #else
  384.     ENUMLOGFONTMINIMAL elfm;
  385.     UINT iFont = 0;
  386.     UINT nFonts;
  387.  
  388.     memset(&elfm.lf, 0, sizeof(LOGFONT));
  389.     while (EnumFontsMinimal(NULL, &elfm, 1, &nFonts, &iFont))
  390.     {
  391.         UINT i = 0;
  392.         VERIFY(EnumFontsMinimal(elfm.lf.lfFaceName, &elfm, 1, &nFonts, &i));
  393.         m_FontNames.AddFont(&elfm.lf, elfm.dwType);
  394.     }
  395.  
  396. #endif
  397.     // Select the first one
  398.     if (m_FontNames.SetCurSel(0) != CB_ERR)
  399.     {
  400.         // Fill the size list
  401.         FillSizeList();
  402.     }
  403.     else
  404.     {
  405.         m_FontNames.EnableWindow(FALSE);
  406.         m_FontSizes.EnableWindow(FALSE);
  407.         m_FontStyles.EnableWindow(FALSE);
  408.         GetDlgItem(AFX_IDC_STRIKEOUT)->EnableWindow(FALSE);
  409.         GetDlgItem(AFX_IDC_UNDERLINE)->EnableWindow(FALSE);
  410.     }
  411. }
  412.  
  413. #ifndef _MAC
  414. int CALLBACK CFontPropPage::EnumFontFamiliesCallBack(ENUMLOGFONT *lpelf, NEWTEXTMETRIC *, int FontType, LPARAM lParam)
  415. {
  416.     CFontPropPage *pDlg = (CFontPropPage *)lParam;
  417.     ASSERT(pDlg);
  418.     pDlg->m_FontNames.AddFont(&lpelf->elfLogFont, FontType);
  419.     return 1;
  420. }
  421. #endif
  422.  
  423. void CFontPropPage::FillSizeList()
  424. {
  425.     // Clear the size list
  426.     m_FontSizes.ResetContent();
  427.     m_FontStyles.ResetContent();
  428.     m_nStyles = 0L;
  429.  
  430.     // Fill with "real" sizes
  431.     CString strFaceName;
  432.     m_FontNames.GetLBText(m_FontNames.GetCurSel(), strFaceName);
  433.     CClientDC dc(NULL);
  434.     int rc = EnumFontFamilies(dc.GetSafeHdc(), (LPCTSTR) strFaceName, (FONTENUMPROC) CFontPropPage::EnumFontFamiliesCallBack2, (LPARAM) this);
  435.  
  436.     // Check if we have a font that is either a vector or Truettype font
  437.     if (m_FontNames.GetFontType() != RASTER_FONTTYPE)
  438.     {
  439.         // Fill with "common" sizes
  440.         static int TTDefaults[] = { 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48 };
  441.         for (int i = 0; i < _countof(TTDefaults); i++)
  442.             m_FontSizes.AddSize(TTDefaults[i], 0);
  443.     }
  444.  
  445.     // See what fonts are native
  446.     BOOL    bRegular = (BOOL)(m_nStyles & NTM_REGULAR);
  447.     BOOL    bBold = (BOOL)(m_nStyles & NTM_BOLD);
  448.     BOOL    bItalic = (BOOL)(m_nStyles & NTM_ITALIC);
  449.     BOOL    bBoldItalic = (BOOL)((m_nStyles & NTM_BOLD) &&
  450.                                  (m_nStyles & NTM_ITALIC));
  451.  
  452.     // Allow for "synthesized" italic && bold variants
  453.     if (bRegular)
  454.         bBold = bItalic = TRUE;
  455.     if (bBold || bItalic)
  456.         bBoldItalic = TRUE;
  457.  
  458.     // Fill the styles list box
  459.     CString strStyle;
  460.  
  461.     int nEntry;
  462.     if (bRegular)
  463.     {
  464.         strStyle.LoadString(AFX_IDS_REGULAR);
  465.         nEntry = m_FontStyles.AddString(strStyle);
  466.         m_FontStyles.SetItemData(nEntry, (DWORD)NTM_REGULAR);
  467.     }
  468.     if (bBold)
  469.     {
  470.         strStyle.LoadString(AFX_IDS_BOLD);
  471.         nEntry = m_FontStyles.AddString(strStyle);
  472.         m_FontStyles.SetItemData(nEntry, (DWORD)NTM_BOLD);
  473.     }
  474.     if (bItalic)
  475.     {
  476.         strStyle.LoadString(AFX_IDS_ITALIC);
  477.         nEntry = m_FontStyles.AddString(strStyle);
  478.         m_FontStyles.SetItemData(nEntry, (DWORD)NTM_ITALIC);
  479.     }
  480.     if (bBoldItalic)
  481.     {
  482.         strStyle.LoadString(AFX_IDS_BOLDITALIC);
  483.         nEntry = m_FontStyles.AddString(strStyle);
  484.         m_FontStyles.SetItemData(nEntry, (DWORD)NTM_ITALIC|NTM_BOLD);
  485.     }
  486.  
  487.     // Set the point size
  488.     if (m_FontSizes.FindString(-1, m_strFontSize) != CB_ERR)
  489.     {
  490.         nEntry = m_FontSizes.SelectString(-1, m_strFontSize);
  491.         if (nEntry == CB_ERR)
  492.             return;
  493.     }
  494.     else
  495.     {
  496.         // Point size is not in the list so just fill the edit box
  497.         // and don't select anything from the list
  498.         m_FontSizes.SetCurSel(-1);
  499.         m_FontSizes.SetWindowText(m_strFontSize);
  500.     }
  501.  
  502.     // Set the styles combo box selection
  503.     BOOL bFound = FALSE;
  504.     int nMaxEntries = m_FontStyles.GetCount();
  505.     for (int nEntry3 = 0; nEntry3 < nMaxEntries; nEntry3++)
  506.     {
  507.         if (m_FontStyles.GetItemData(nEntry3) == m_nActualStyle)
  508.         {
  509.             m_FontStyles.SetCurSel(nEntry3);
  510.             bFound = TRUE;
  511.         }
  512.     }
  513.  
  514.     if (!bFound)
  515.     {
  516.         m_FontStyles.SetCurSel(0);      // Set style to regular
  517.         m_nCurrentStyle = NTM_REGULAR;
  518.     }
  519.     else
  520.         m_nCurrentStyle = m_nActualStyle;
  521.  
  522.     // Redraw the sample
  523.     UpdateSampleFont();
  524. }
  525.  
  526. int CALLBACK CFontPropPage::EnumFontFamiliesCallBack2(
  527.     ENUMLOGFONT* lpelf, NEWTEXTMETRIC* lpntm, int FontType, LPARAM lParam)
  528. {
  529.     CFontPropPage *pDlg = (CFontPropPage *)lParam;
  530.     ASSERT(pDlg != NULL);
  531.  
  532.     if (FontType & TRUETYPE_FONTTYPE)
  533.     {
  534.         if (!(lpntm->ntmFlags & (NTM_BOLD | NTM_ITALIC)))
  535.             pDlg->m_nStyles |= NTM_REGULAR;
  536.  
  537.         if (lpntm->ntmFlags & NTM_ITALIC)
  538.             pDlg->m_nStyles |= NTM_ITALIC;
  539.  
  540.         if (lpntm->ntmFlags & NTM_BOLD)
  541.             pDlg->m_nStyles |= NTM_BOLD;
  542.     }
  543.     else
  544.     {
  545.         if (FontType & RASTER_FONTTYPE)
  546.         {
  547.             int height = lpntm->tmHeight - lpntm->tmInternalLeading;
  548.             pDlg->m_FontSizes.AddSize(MulDiv(height, 72, afxData.cyPixelsPerInch), height);
  549.         }
  550.  
  551.         if (lpelf->elfLogFont.lfWeight >= FW_BOLD && lpelf->elfLogFont.lfItalic)
  552.             pDlg->m_nStyles |= NTM_BOLD | NTM_ITALIC;
  553.         else if (lpelf->elfLogFont.lfWeight >= FW_BOLD)
  554.             pDlg->m_nStyles |= NTM_BOLD;
  555.         else if (lpelf->elfLogFont.lfItalic)
  556.             pDlg->m_nStyles |= NTM_ITALIC;
  557.         else
  558.             pDlg->m_nStyles |= NTM_REGULAR;
  559.     }
  560.  
  561.     return 1;
  562. }
  563.  
  564. #define DX_BITMAP        20
  565. #define DY_BITMAP        12
  566.  
  567. /////////////////////////////////////////////////////////////////////////////
  568. // CFontComboBox
  569.  
  570. CFontComboBox::CFontComboBox() : CComboBox()
  571. {
  572.     m_bmpTrueType.LoadBitmap(AFX_IDB_TRUETYPE);
  573.     _AfxInitMaskFromBitmap(&m_bmpTrueType, &m_bmpMask);
  574. }
  575.  
  576. CFontComboBox::~CFontComboBox()
  577. {
  578. }
  579.  
  580. int CFontComboBox::AddFont(LOGFONT *pLF, DWORD FontType)
  581. {
  582.     int nEntry;
  583.     FONTITEM_PPG* pFontItem = NULL;
  584.  
  585.     // Font already in the combobox
  586.     if (FindString(-1, (LPCTSTR) pLF->lfFaceName) != CB_ERR)
  587.         return CB_ERR;
  588.  
  589.     // allocate some memory for the FONTITEM_PPG structure
  590.     TRY
  591.     {
  592.         pFontItem = new FONTITEM_PPG;
  593.     }
  594.     CATCH( CMemoryException, e )
  595.     {
  596.         return CB_ERR;
  597.     }
  598.     END_CATCH
  599.  
  600.     ASSERT( pFontItem );
  601.     pFontItem->lf = *pLF;
  602.     pFontItem->dwFontType = FontType;
  603.  
  604.     nEntry = AddString( (LPCTSTR) pFontItem->lf.lfFaceName );
  605.  
  606.     if (nEntry == CB_ERR)
  607.         delete pFontItem;
  608.     else
  609.         SetItemData( nEntry, (DWORD) pFontItem );
  610.  
  611.     return nEntry;
  612. }
  613.  
  614. FONTITEM_PPG* CFontComboBox::GetFontItem(int sel)
  615. {
  616.     if (sel == -1)
  617.         sel = GetCurSel();
  618.  
  619.     if (sel == -1)
  620.     {
  621.         CString str;
  622.  
  623.         GetWindowText( str );
  624.         sel = FindString( -1, str );
  625.         if (sel == CB_ERR)
  626.             sel = 0;
  627.     }
  628.  
  629.     ASSERT( GetItemData(sel) );
  630.     return (FONTITEM_PPG*) GetItemData(sel);
  631. }
  632.  
  633. LPLOGFONT CFontComboBox::GetLogFont(int sel)
  634. {
  635.     return &GetFontItem(sel)->lf;
  636. }
  637.  
  638. DWORD CFontComboBox::GetFontType(int sel)
  639. {
  640.     return GetFontItem(sel)->dwFontType;
  641. }
  642.  
  643. CString CFontComboBox::GetCurrentName()
  644. {
  645.     CString str;
  646.     GetWindowText(str);
  647.     return str;
  648. }
  649.  
  650. void CFontComboBox::DrawItem(LPDRAWITEMSTRUCT lpDIS)
  651. {
  652.     ASSERT( lpDIS->CtlType == ODT_COMBOBOX );
  653.  
  654.     // make sure this is a *real* item
  655.     if (lpDIS->itemID == -1)
  656.         return;
  657.  
  658.     CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  659.     FONTITEM_PPG* pFI = (FONTITEM_PPG*)lpDIS->itemData;    // pointer to a FONTITEM storied in item data
  660.     LOGFONT* pLF = &pFI->lf;
  661.     COLORREF crBk, crText;
  662.     TEXTMETRIC tm;
  663.     int x, y;
  664.  
  665.     // Calculate the colors to use
  666.     crBk = pDC->SetBkColor(
  667.         GetSysColor(lpDIS->itemState & ODS_SELECTED ? COLOR_HIGHLIGHT : COLOR_WINDOW) );
  668.     crText = pDC->SetTextColor(
  669.         GetSysColor(lpDIS->itemState & ODS_SELECTED ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT) );
  670.  
  671.     // Calculate the position of the text
  672.     pDC->GetTextMetrics( &tm );
  673.     x = LOWORD(GetDialogBaseUnits()) / 4;
  674.     y = (lpDIS->rcItem.bottom + lpDIS->rcItem.top - tm.tmHeight) / 2;
  675.  
  676.     // Draw the text
  677.     pDC->ExtTextOut(lpDIS->rcItem.left + DX_BITMAP + 2 * x, y, ETO_CLIPPED | ETO_OPAQUE,
  678.         &lpDIS->rcItem,(LPCTSTR) pLF->lfFaceName,
  679.         lstrlen((LPCTSTR) pLF->lfFaceName), NULL );
  680.  
  681.     // Put the colors back as they were
  682.     pDC->SetTextColor( crText );
  683.     pDC->SetBkColor( crBk );
  684.  
  685.     // Draw the TrueType bitmap
  686.     if (pFI->dwFontType & TRUETYPE_FONTTYPE)
  687.     {
  688.         int dy;
  689.         dy = ((lpDIS->rcItem.bottom - lpDIS->rcItem.top) - DY_BITMAP) / 2;
  690.         _AfxDrawMaskedBitmap(pDC, &m_bmpTrueType, &m_bmpMask,
  691.             x, lpDIS->rcItem.top + dy, DX_BITMAP, DY_BITMAP);
  692.     }
  693.  
  694.     // Draw the focus rect if needed
  695.     if (lpDIS->itemState & ODS_FOCUS)
  696.         pDC->DrawFocusRect( &lpDIS->rcItem );
  697. }
  698.  
  699. void CFontComboBox::DeleteItem(LPDELETEITEMSTRUCT lpDIS)
  700. {
  701.     FONTITEM_PPG* pFI;
  702.  
  703.     if (lpDIS->itemID == -1)
  704.         return;
  705.  
  706.     ASSERT( lpDIS->CtlType == ODT_COMBOBOX );
  707.  
  708.     pFI = GetFontItem(lpDIS->itemID);
  709.  
  710.     // Free the FONTITEM_PPG created in CFontComboBox::AddFont()
  711.     ASSERT(pFI);
  712.     delete pFI;
  713. }
  714.  
  715. /////////////////////////////////////////////////////////////////////////////
  716. // CSizeComboBox
  717.  
  718. int CSizeComboBox::AddSize(int PointSize, LONG lfHeight)
  719. {
  720.     if (lfHeight == 0)
  721.         lfHeight = MulDiv( -afxData.cyPixelsPerInch, PointSize, 72 );
  722.  
  723.     CString str;
  724.     wsprintf(str.GetBuffer(16), _T("%d"), PointSize);
  725.     str.ReleaseBuffer();
  726.  
  727.     int nMaxEntries = GetCount();
  728.     int nEntry;
  729.  
  730.     // we use positive height values for non-truetype fonts, negitive for true type
  731.     if (lfHeight > 0)
  732.     {
  733.         for (nEntry = 0; nEntry < nMaxEntries; nEntry++)
  734.         {
  735.             int iComp = (int)(lfHeight - GetHeight(nEntry));
  736.             if (!iComp)
  737.                 return CB_ERR;
  738.             if (iComp < 0)
  739.                 break;
  740.         }
  741.     }
  742.     else
  743.     {
  744.         for (nEntry = 0; nEntry < nMaxEntries; nEntry++)
  745.         {
  746.             int iComp = (int)(lfHeight - GetHeight(nEntry));
  747.             if (!iComp)
  748.                 return CB_ERR;
  749.             if (iComp > 0)
  750.                 break;
  751.         }
  752.     }
  753.  
  754.     if (nEntry == nMaxEntries)
  755.         nEntry = -1;
  756.     nEntry = InsertString(nEntry, str);
  757.     if (nEntry != CB_ERR)
  758.         SetItemData(nEntry, (DWORD)lfHeight);
  759.  
  760.     return nEntry;
  761. }
  762.  
  763. void CSizeComboBox::GetPointSize(CY& cy)
  764. {
  765.     TCHAR szText[20];
  766.     GetWindowText(szText, 20);
  767.     cy.Lo = 0;
  768.     cy.Hi = 0;
  769.     _AfxCyFromString(cy, szText);
  770. }
  771.  
  772. LONG CSizeComboBox::GetHeight(int sel)
  773. {
  774.     if (sel == -1)
  775.         sel = GetCurSel();
  776.  
  777.     if (sel == -1)
  778.     {
  779.         TCHAR szText[20];
  780.         GetWindowText(szText, 20);
  781.         sel = FindString( -1, szText);
  782.         if (sel == CB_ERR)
  783.         {
  784.             CY cyTmp;
  785.             cyTmp.Lo = 0;
  786.             cyTmp.Hi = 0;
  787.             _AfxCyFromString(cyTmp, szText);
  788.             int PointSize = (int)((cyTmp.Lo + 5000) / 10000);
  789.             if (PointSize != 0)
  790.                 return MulDiv(-afxData.cyPixelsPerInch, PointSize, 72);
  791.             else
  792.                 sel = 0;
  793.         }
  794.     }
  795.  
  796.     return (LONG) GetItemData(sel);
  797. }
  798.  
  799. void CSizeComboBox::UpdateLogFont( LPLOGFONT lpLF, int sel )
  800. {
  801.     ASSERT(lpLF);
  802.  
  803.     lpLF->lfHeight = (int)GetHeight(sel);
  804.     lpLF->lfWidth = 0;
  805. }
  806.  
  807. /////////////////////////////////////////////////////////////////////////////
  808. // CFontPropPage message handlers
  809.  
  810. void CFontPropPage::OnEditupdateFontnames()
  811. {
  812.     // When the users entry matches an entry in the list, select it
  813.     CString str;
  814.     m_FontNames.GetWindowText(str);
  815.     int nEntry = m_FontNames.FindStringExact(-1, str);
  816.     if (nEntry != CB_ERR)
  817.     {
  818.         m_FontNames.SetCurSel(nEntry);
  819.         m_FontNames.SetEditSel(-1, -1);
  820.  
  821.         // Re-fill the size list
  822.         FillSizeList();
  823.     }
  824. }
  825.  
  826. void CFontPropPage::OnEditupdateFontsizes()
  827. {
  828.     // when the users entry matches an entry in the list, select it
  829.     m_FontSizes.GetWindowText(m_strFontSize);
  830.     int nEntry = m_FontSizes.FindStringExact(-1, m_strFontSize);
  831.     if (nEntry != CB_ERR)
  832.     {
  833.         m_FontSizes.SetCurSel(nEntry);
  834.         m_FontSizes.SetEditSel(-1, -1);
  835.  
  836.         // Update the sample text
  837.         UpdateSampleFont();
  838.     }
  839. }
  840.  
  841. void CFontPropPage::OnSelchangeFontnames()
  842. {
  843.     FillSizeList();
  844. }
  845.  
  846. void CFontPropPage::UpdateSampleFont()
  847. {
  848.     ASSERT(m_FontNames.GetFontItem());
  849.  
  850.     LOGFONT lf = *m_FontNames.GetLogFont();
  851.     m_FontSizes.UpdateLogFont( &lf );
  852.  
  853.     // Handle styles
  854.     if (m_nCurrentStyle & NTM_BOLD)
  855.         lf.lfWeight = FW_BOLD;
  856.     else
  857.         lf.lfWeight = FW_REGULAR;
  858.     if (m_nCurrentStyle & NTM_ITALIC)
  859.         lf.lfItalic = TRUE;
  860.     else
  861.         lf.lfItalic = FALSE;
  862.  
  863.     lf.lfStrikeOut = (unsigned char)m_bStrikeOut;
  864.     lf.lfUnderline = (unsigned char)m_bUnderline;
  865.  
  866.     SampleFont.DeleteObject();
  867.     SampleFont.CreateFontIndirect( &lf );
  868.  
  869.     CRect rcSample;
  870.     m_SampleBox.GetWindowRect( &rcSample );
  871.     ScreenToClient( &rcSample );
  872.  
  873.     InvalidateRect( rcSample );
  874.     UpdateWindow();
  875. }
  876.  
  877. void CFontPropPage::OnPaint()
  878. {
  879.     CPaintDC dc(this);
  880.     CRect rcText;
  881.     CFont *oldFont;
  882.     CSize TextExtent;
  883.     COLORREF crText;
  884.     TEXTMETRIC tm;
  885.     int bkMode, len, x, y;
  886.     CString strSample;
  887.  
  888.     strSample.LoadString(AFX_IDS_SAMPLETEXT);
  889.  
  890.     // If there is no sample font abort
  891.     if (!SampleFont.GetSafeHandle())
  892.         return;
  893.  
  894.     // Get the bounding box
  895.     m_SampleBox.GetWindowRect( &rcText );
  896.     ScreenToClient( &rcText );
  897.  
  898.     // Select the new font and colors into the dc
  899.     oldFont = dc.SelectObject( &SampleFont );
  900.     crText = dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
  901.     bkMode = dc.SetBkMode(TRANSPARENT);
  902.  
  903.     // Calculate the position of the text
  904.     dc.GetTextMetrics( &tm );
  905.  
  906.     len = strSample.GetLength();
  907.     TextExtent = dc.GetTextExtent(strSample, len);
  908.     TextExtent.cy = tm.tmAscent - tm.tmInternalLeading;
  909.  
  910.     if ((TextExtent.cx >= (rcText.right - rcText.left)) ||
  911.             (TextExtent.cx <= 0))
  912.         x = rcText.left;
  913.     else
  914.         x = rcText.left + ((rcText.right - rcText.left) - TextExtent.cx) / 2;
  915.  
  916.     y = min(rcText.bottom,
  917.         rcText.bottom - ((rcText.bottom - rcText.top) - TextExtent.cy) / 2);
  918.  
  919.     // Draw it
  920.     dc.ExtTextOut(x, y - (tm.tmAscent), ETO_CLIPPED, &rcText,
  921.         strSample, len, NULL);
  922.  
  923.     // Put the DC back the way it was
  924.     dc.SetBkMode(bkMode);
  925.     dc.SetTextColor(crText);
  926.  
  927.     if (oldFont)
  928.         dc.SelectObject(oldFont);
  929. }
  930.  
  931. void CFontPropPage::OnSelchangeFontsizes()
  932. {
  933.     int nEntry = m_FontSizes.GetCurSel();
  934.     if (nEntry != CB_ERR)
  935.     {
  936.         m_FontSizes.GetLBText(nEntry, m_strFontSize);
  937.         UpdateSampleFont();
  938.     }
  939. }
  940. void CFontPropPage::OnSelchangeFontstyles()
  941. {
  942.     int nEntry = m_FontStyles.GetCurSel();
  943.     m_nCurrentStyle = m_FontStyles.GetItemData(nEntry);
  944.     m_nActualStyle = m_nCurrentStyle;
  945.  
  946.     // Update the sample font
  947.     UpdateSampleFont();
  948. }
  949.  
  950. void CFontPropPage::OnEditchangeFontstyles()
  951. {
  952.     // when the users entry matches an entry in the list, select it
  953.     CString str;
  954.     m_FontStyles.GetWindowText(str);
  955.     int nEntry = m_FontStyles.FindStringExact(-1, str);
  956.     if (nEntry != CB_ERR)
  957.     {
  958.         m_FontStyles.SetCurSel(nEntry);
  959.         m_FontStyles.SetEditSel(-1, -1);
  960.  
  961.         // Update the sample text
  962.         m_nCurrentStyle = m_FontStyles.GetItemData(nEntry);
  963.         m_nActualStyle = m_nCurrentStyle;
  964.         UpdateSampleFont();
  965.     }
  966. }
  967.  
  968. void CFontPropPage::SelectFontFromList(CString strFaceName, MERGEOBJECT* pmobj)
  969. {
  970.     // Set the effects buttons
  971.     CButton* pStrikeOut = (CButton*) GetDlgItem(AFX_IDC_STRIKEOUT);
  972.     if (!pmobj->bStrikethroughOK)
  973.         pStrikeOut->SetCheck(2);
  974.     else if (m_bStrikeOut)
  975.         pStrikeOut->SetCheck(1);
  976.     else
  977.         pStrikeOut->SetCheck(0);
  978.  
  979.     CButton* pUnderline = (CButton*) GetDlgItem(AFX_IDC_UNDERLINE);
  980.     if (!pmobj->bUnderlineOK)
  981.         pStrikeOut->SetCheck(2);
  982.     else if (m_bUnderline)
  983.         pUnderline->SetCheck(1);
  984.     else
  985.         pUnderline->SetCheck(0);
  986.  
  987.     // Set the font facename
  988.     if (pmobj->bNameOK)
  989.     {
  990.         int nEntry1 = m_FontNames.SelectString(-1, strFaceName);
  991.         if (nEntry1 == CB_ERR)
  992.             return;
  993.     }
  994.  
  995.     // Fill the size list appropriately
  996.     FillSizeList();
  997.  
  998.     // Set the styles combo box selection
  999.     BOOL bFound = FALSE;
  1000.     int nMaxEntries = m_FontStyles.GetCount();
  1001.     for (int nEntry3 = 0; nEntry3 < nMaxEntries; nEntry3++)
  1002.     {
  1003.         if (m_FontStyles.GetItemData(nEntry3) == m_nActualStyle)
  1004.         {
  1005.             m_FontStyles.SetCurSel(nEntry3);
  1006.             bFound = TRUE;
  1007.         }
  1008.     }
  1009.  
  1010.     if (pmobj->bSizeOK)
  1011.     {
  1012.         if (!bFound)
  1013.         {
  1014.             m_FontStyles.SetCurSel(0);      // Set style to regular
  1015.             m_nCurrentStyle = NTM_REGULAR;
  1016.         }
  1017.         else
  1018.             m_nCurrentStyle = m_nActualStyle;
  1019.     }
  1020.  
  1021.     UpdateSampleFont();
  1022. }
  1023.  
  1024. void CFontPropPage::OnStrikeout()
  1025. {
  1026.     CButton* pStrikeOut = (CButton*) GetDlgItem(AFX_IDC_STRIKEOUT);
  1027.     if (pStrikeOut->GetCheck() == 1)
  1028.         m_bStrikeOut = TRUE;
  1029.     else
  1030.         m_bStrikeOut = FALSE;
  1031.  
  1032.     UpdateSampleFont();
  1033. }
  1034.  
  1035. void CFontPropPage::OnUnderline()
  1036. {
  1037.     CButton* pUnderline = (CButton*) GetDlgItem(AFX_IDC_UNDERLINE);
  1038.     if (pUnderline->GetCheck() == 1)
  1039.         m_bUnderline = TRUE;
  1040.     else
  1041.         m_bUnderline = FALSE;
  1042.  
  1043.     UpdateSampleFont();
  1044. }
  1045.  
  1046. void CFontPropPage::OnSelchangeFontprop()
  1047. {
  1048.     OnSelchangePropname(m_FontProp);
  1049. }
  1050.  
  1051. BOOL CFontPropPage::OnEditProperty(DISPID dispid)
  1052. {
  1053.     return CStockPropPage::OnEditProperty(dispid, m_FontProp);
  1054. }
  1055.  
  1056. void CFontPropPage::OnObjectsChanged()
  1057. {
  1058.     ULONG nObjects;
  1059.     if (GetObjectArray(&nObjects) != NULL && m_hWnd != NULL)
  1060.     {
  1061.         FillPropnameList(IID_IFontDisp, 1, m_FontProp);
  1062.  
  1063.         if ( m_FontProp.GetCount() > 0 )
  1064.             FillFacenameList();
  1065.         else
  1066.         {
  1067.             m_FontNames.EnableWindow(FALSE);
  1068.             m_FontSizes.EnableWindow(FALSE);
  1069.             m_FontStyles.EnableWindow(FALSE);
  1070.             GetDlgItem(AFX_IDC_STRIKEOUT)->EnableWindow(FALSE);
  1071.             GetDlgItem(AFX_IDC_UNDERLINE)->EnableWindow(FALSE);
  1072.         }
  1073.     }
  1074.  
  1075.     if (m_hWnd != NULL)
  1076.         OnSelchangeFontprop();
  1077. }
  1078.  
  1079. /////////////////////////////////////////////////////////////////////////////
  1080. // Class factory for Font property page
  1081.  
  1082. #ifdef AFXCTL_FACT_SEG
  1083. #pragma code_seg(AFXCTL_FACT_SEG)
  1084. #endif
  1085.  
  1086. IMPLEMENT_OLECREATE_EX(CFontPropPage, "OCxx.CFontPropPage",
  1087.     0x0be35200,0x8f91,0x11ce,0x9d,0xe3,0x00,0xaa,0x00,0x4b,0xb8,0x51)
  1088.  
  1089. BOOL CFontPropPage::CFontPropPageFactory::UpdateRegistry(BOOL bRegister)
  1090. {
  1091.     if (bRegister)
  1092.         return AfxOleRegisterPropertyPageClass(AfxGetInstanceHandle(),
  1093.             m_clsid, AFX_IDS_FONT_PPG);
  1094.     else
  1095.         return AfxOleUnregisterClass(m_clsid, NULL);
  1096. }
  1097.  
  1098. /////////////////////////////////////////////////////////////////////////////
  1099. // Force any extra compiler-generated code into AFX_INIT_SEG
  1100.  
  1101. #ifdef AFX_INIT_SEG
  1102. #pragma code_seg(AFX_INIT_SEG)
  1103. #endif
  1104.  
  1105. IMPLEMENT_DYNCREATE(CFontPropPage, CStockPropPage)
  1106.