home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / dlgtempl.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  10KB  |  404 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 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 AFX_CORE1_SEG
  14. #pragma code_seg(AFX_CORE1_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. // _AfxConvertDialogUnitsToPixels
  26.  
  27. AFX_STATIC void AFXAPI _AfxConvertDialogUnitsToPixels(LPCTSTR pszFontFace, WORD wFontSize,
  28.     int cxDlg, int cyDlg, SIZE* pSizePixel)
  29. {
  30.     // Attempt to create the font to be used in the dialog box
  31.     UINT cxSysChar, cySysChar;
  32.     LOGFONT lf;
  33.     HDC hDC = ::GetDC(NULL);
  34.     memset(&lf, 0, sizeof(LOGFONT));
  35.     lf.lfHeight = -MulDiv(wFontSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);
  36.     lf.lfWeight = FW_NORMAL;
  37.     lf.lfCharSet = DEFAULT_CHARSET;
  38.     lstrcpy(lf.lfFaceName, pszFontFace);
  39.  
  40.     HFONT hNewFont = CreateFontIndirect(&lf);
  41.     if (hNewFont != NULL)
  42.     {
  43.         HFONT hFontOld = (HFONT)SelectObject(hDC, hNewFont);
  44.         TEXTMETRIC tm;
  45.         GetTextMetrics(hDC, &tm);
  46.         cySysChar = tm.tmHeight + tm.tmExternalLeading;
  47.         SIZE size;
  48.         ::GetTextExtentPoint32(hDC,
  49.             _T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52,
  50.             &size);
  51.         cxSysChar = (size.cx + 26) / 52;
  52.         SelectObject(hDC, hFontOld);
  53.         DeleteObject(hNewFont);
  54.     }
  55.     else
  56.     {
  57.         // Could not create the font so just use the system's values
  58.         cxSysChar = LOWORD(GetDialogBaseUnits());
  59.         cySysChar = HIWORD(GetDialogBaseUnits());
  60.     }
  61.     ::ReleaseDC(NULL, hDC);
  62.  
  63.     // Translate dialog units to pixels
  64.     pSizePixel->cx = MulDiv(cxDlg, cxSysChar, 4);
  65.     pSizePixel->cy = MulDiv(cyDlg, cySysChar, 8);
  66. }
  67.  
  68. /////////////////////////////////////////////////////////////////////////////
  69. // IsDialogEx
  70.  
  71. AFX_STATIC inline BOOL IsDialogEx(const DLGTEMPLATE* pTemplate)
  72. {
  73.     return ((DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF;
  74. }
  75.  
  76. /////////////////////////////////////////////////////////////////////////////
  77. // HasFont
  78.  
  79. AFX_STATIC inline BOOL HasFont(const DLGTEMPLATE* pTemplate)
  80. {
  81.     return (DS_SETFONT &
  82.         (IsDialogEx(pTemplate) ? ((DLGTEMPLATEEX*)pTemplate)->style :
  83.         pTemplate->style));
  84. }
  85.  
  86. /////////////////////////////////////////////////////////////////////////////
  87. // FontAttrSize
  88.  
  89. AFX_STATIC inline int FontAttrSize(BOOL bDialogEx)
  90. {
  91.     return sizeof(WORD) * (bDialogEx ? 3 : 1);
  92. }
  93.  
  94. /////////////////////////////////////////////////////////////////////////////
  95. // CDialogTemplate - implementation class
  96.  
  97. CDialogTemplate::CDialogTemplate(const DLGTEMPLATE* pTemplate)
  98. {
  99.     if (pTemplate == NULL)
  100.     {
  101.         m_hTemplate = NULL;
  102.         m_dwTemplateSize = 0;
  103.         m_bSystemFont = FALSE;
  104.     }
  105.     else
  106.     {
  107.         SetTemplate(pTemplate, GetTemplateSize(pTemplate));
  108.     }
  109. }
  110.  
  111. CDialogTemplate::CDialogTemplate(HGLOBAL hTemplate)
  112. {
  113.     if (hTemplate == NULL)
  114.     {
  115.         m_hTemplate = NULL;
  116.         m_dwTemplateSize = 0;
  117.         m_bSystemFont = FALSE;
  118.     }
  119.     else
  120.     {
  121.         DLGTEMPLATE* pTemplate = (DLGTEMPLATE*)GlobalLock(hTemplate);
  122.         SetTemplate(pTemplate, GetTemplateSize(pTemplate));
  123.         GlobalUnlock(hTemplate);
  124.     }
  125. }
  126.  
  127. BOOL CDialogTemplate::SetTemplate(const DLGTEMPLATE* pTemplate, UINT cb)
  128. {
  129.     m_dwTemplateSize = cb;
  130.  
  131.     if ((m_hTemplate = GlobalAlloc(GPTR, m_dwTemplateSize + LF_FACESIZE * 2)) == NULL)
  132.         return FALSE;
  133.     DLGTEMPLATE* pNew = (DLGTEMPLATE*)GlobalLock(m_hTemplate);
  134.     memcpy((BYTE*)pNew, pTemplate, (size_t)m_dwTemplateSize);
  135.  
  136.     m_bSystemFont = (::HasFont(pNew) == 0);
  137.  
  138.     GlobalUnlock(m_hTemplate);
  139.     return TRUE;
  140. }
  141.  
  142. CDialogTemplate::~CDialogTemplate()
  143. {
  144.     if (m_hTemplate != NULL)
  145.         GlobalFree(m_hTemplate);
  146. }
  147.  
  148. BOOL CDialogTemplate::Load(LPCTSTR lpDialogTemplateID)
  149. {
  150.     HINSTANCE hInst = AfxFindResourceHandle(lpDialogTemplateID, RT_DIALOG);
  151.     if (hInst == NULL)
  152.         return FALSE;
  153.     HRSRC hRsrc = FindResource(hInst, lpDialogTemplateID, RT_DIALOG);
  154.     if (hRsrc == NULL)
  155.         return FALSE;
  156.     HGLOBAL hTemplate = LoadResource(hInst, hRsrc);
  157.     DLGTEMPLATE* pTemplate = (DLGTEMPLATE*)LockResource(hTemplate);
  158.     SetTemplate(pTemplate, (UINT)SizeofResource(hInst, hRsrc));
  159.     UnlockResource(hTemplate);
  160.     FreeResource(hTemplate);
  161.     return TRUE;
  162. }
  163.  
  164. HGLOBAL CDialogTemplate::Detach()
  165. {
  166.     HGLOBAL hTmp = m_hTemplate;
  167.     m_hTemplate = NULL;
  168.     return hTmp;
  169. }
  170.  
  171. BOOL CDialogTemplate::HasFont() const
  172. {
  173.     DLGTEMPLATE* pTemplate = (DLGTEMPLATE*)GlobalLock(m_hTemplate);
  174.     BOOL bHasFont = ::HasFont(pTemplate);
  175.     GlobalUnlock(m_hTemplate);
  176.     return bHasFont;
  177. }
  178.  
  179. inline WCHAR* _SkipString(WCHAR* p)
  180. {
  181.     while (*p++);
  182.     return p;
  183. }
  184.  
  185. BYTE* AFX_CDECL CDialogTemplate::GetFontSizeField(const DLGTEMPLATE* pTemplate)
  186. {
  187.     BOOL bDialogEx = IsDialogEx(pTemplate);
  188.     WORD* pw;
  189.  
  190.     if (bDialogEx)
  191.         pw = (WORD*)((DLGTEMPLATEEX*)pTemplate + 1);
  192.     else
  193.         pw = (WORD*)(pTemplate + 1);
  194.  
  195.     if (*pw == (WORD)-1)        // Skip menu name string or ordinal
  196.         pw += 2; // WORDs
  197.     else
  198.         while(*pw++);
  199.  
  200.     if (*pw == (WORD)-1)        // Skip class name string or ordinal
  201.         pw += 2; // WORDs
  202.     else
  203.         while(*pw++);
  204.  
  205.     while (*pw++);          // Skip caption string
  206.  
  207.     return (BYTE*)pw;
  208. }
  209.  
  210. UINT AFX_CDECL CDialogTemplate::GetTemplateSize(const DLGTEMPLATE* pTemplate)
  211. {
  212.     BOOL bDialogEx = IsDialogEx(pTemplate);
  213.     BYTE* pb = GetFontSizeField(pTemplate);
  214.  
  215.     if (::HasFont(pTemplate))
  216.     {
  217.         // Skip font size and name
  218.         pb += FontAttrSize(bDialogEx);  // Skip font size, weight, (italic, charset)
  219.         pb += 2 * (wcslen((WCHAR*)pb) + 1);
  220.     }
  221.  
  222.     WORD nCtrl = bDialogEx ? (WORD)((DLGTEMPLATEEX*)pTemplate)->cDlgItems :
  223.         (WORD)pTemplate->cdit;
  224.  
  225.     while (nCtrl > 0)
  226.     {
  227.         pb = (BYTE*)(((DWORD)pb + 3) & ~3); // DWORD align
  228.  
  229.         pb += (bDialogEx ? sizeof(DLGITEMTEMPLATEEX) : sizeof(DLGITEMTEMPLATE));
  230.  
  231.         if (*(WORD*)pb == (WORD)-1)     // Skip class name string or ordinal
  232.             pb += 2 * sizeof(WORD);
  233.         else
  234.             pb = (BYTE*)_SkipString((WCHAR*)pb);
  235.  
  236.         if (*(WORD*)pb == (WORD)-1)     // Skip text string or ordinal
  237.             pb += 2 * sizeof(WORD);
  238.         else
  239.             pb = (BYTE*)_SkipString((WCHAR*)pb);
  240.  
  241.         WORD cbExtra = *(WORD*)pb;      // Skip extra data
  242.         pb += sizeof(WORD) + cbExtra;
  243.         --nCtrl;
  244.     }
  245.  
  246.     return pb - (BYTE*)pTemplate;
  247. }
  248.  
  249. BOOL AFX_CDECL CDialogTemplate::GetFont(const DLGTEMPLATE* pTemplate,
  250.     CString& strFace, WORD& nFontSize)
  251. {
  252.     ASSERT(pTemplate != NULL);
  253.  
  254.     if (!::HasFont(pTemplate))
  255.         return FALSE;
  256.  
  257.     BYTE* pb = GetFontSizeField(pTemplate);
  258.     nFontSize = *(WORD*)pb;
  259.     pb += FontAttrSize(IsDialogEx(pTemplate));
  260.  
  261. #if defined(_UNICODE) || defined(OLE2ANSI)
  262.     // Copy font name
  263.     strFace = (LPCTSTR)pb;
  264. #else
  265.     // Convert Unicode font name to MBCS
  266.     WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pb, -1,
  267.         strFace.GetBufferSetLength(LF_FACESIZE), LF_FACESIZE, NULL, NULL);
  268.     strFace.ReleaseBuffer();
  269. #endif
  270.  
  271.     return TRUE;
  272. }
  273.  
  274. BOOL CDialogTemplate::GetFont(CString& strFace, WORD& nFontSize) const
  275. {
  276.     ASSERT(m_hTemplate != NULL);
  277.  
  278.     DLGTEMPLATE* pTemplate = (DLGTEMPLATE*)GlobalLock(m_hTemplate);
  279.     BOOL bResult = GetFont(pTemplate, strFace, nFontSize);
  280.     GlobalUnlock(m_hTemplate);
  281.     return bResult;
  282. }
  283.  
  284. BOOL CDialogTemplate::SetFont(LPCTSTR lpFaceName, WORD nFontSize)
  285. {
  286.     ASSERT(m_hTemplate != NULL);
  287.  
  288.     if (m_dwTemplateSize == 0)
  289.         return FALSE;
  290.  
  291.     DLGTEMPLATE* pTemplate = (DLGTEMPLATE*)GlobalLock(m_hTemplate);
  292.  
  293.     BOOL bDialogEx = IsDialogEx(pTemplate);
  294.     BOOL bHasFont = ::HasFont(pTemplate);
  295.     int cbFontAttr = FontAttrSize(bDialogEx);
  296.  
  297.     if (bDialogEx)
  298.         ((DLGTEMPLATEEX*)pTemplate)->style |= DS_SETFONT;
  299.     else
  300.         pTemplate->style |= DS_SETFONT;
  301.  
  302. #ifdef _UNICODE
  303.     int cbNew = cbFontAttr + ((lstrlen(lpFaceName) + 1) * sizeof(TCHAR));
  304.     BYTE* pbNew = (BYTE*)lpFaceName;
  305. #else
  306.     WCHAR wszFaceName [LF_FACESIZE];
  307.     int cbNew = cbFontAttr + 2 * MultiByteToWideChar(CP_ACP, 0, lpFaceName, -1, wszFaceName, LF_FACESIZE);
  308.     BYTE* pbNew = (BYTE*)wszFaceName;
  309. #endif
  310.  
  311.     BYTE* pb = GetFontSizeField(pTemplate);
  312.     int cbOld = bHasFont ? cbFontAttr + 2 * (wcslen((WCHAR*)(pb + cbFontAttr)) + 1) : 0;
  313.  
  314.     BYTE* pOldControls = (BYTE*)(((DWORD)pb + cbOld + 3) & ~3);
  315.     BYTE* pNewControls = (BYTE*)(((DWORD)pb + cbNew + 3) & ~3);
  316.  
  317.     WORD nCtrl = bDialogEx ? (WORD)((DLGTEMPLATEEX*)pTemplate)->cDlgItems :
  318.         (WORD)pTemplate->cdit;
  319.  
  320.     if (cbNew != cbOld && nCtrl > 0)
  321.         memmove(pNewControls, pOldControls, (size_t)(m_dwTemplateSize - (pOldControls - (BYTE*)pTemplate)));
  322.  
  323.     *(WORD*)pb = nFontSize;
  324.     memmove(pb + cbFontAttr, pbNew, cbNew - cbFontAttr);
  325.  
  326.     m_dwTemplateSize += (pNewControls - pOldControls);
  327.  
  328.     GlobalUnlock(m_hTemplate);
  329.     m_bSystemFont = FALSE;
  330.     return TRUE;
  331. }
  332.  
  333. BOOL CDialogTemplate::SetSystemFont(WORD wSize)
  334. {
  335.     LPCTSTR pszFace = _T("System");
  336.     WORD wDefSize = 10;
  337.     HFONT hFont = (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
  338.     if (hFont == NULL)
  339.         hFont = (HFONT)::GetStockObject(SYSTEM_FONT);
  340.     if (hFont != NULL)
  341.     {
  342.         LOGFONT lf;
  343.         if (::GetObject(hFont, sizeof(LOGFONT), &lf) != 0)
  344.         {
  345.             pszFace = lf.lfFaceName;
  346.             HDC hDC = ::GetDC(NULL);
  347.             if (lf.lfHeight < 0)
  348.                 lf.lfHeight = -lf.lfHeight;
  349.             wDefSize = (WORD)MulDiv(lf.lfHeight, 72, GetDeviceCaps(hDC, LOGPIXELSY));
  350.             ::ReleaseDC(NULL, hDC);
  351.         }
  352.     }
  353.  
  354.     if (wSize == 0)
  355.         wSize = wDefSize;
  356.  
  357.     return SetFont(pszFace, wSize);
  358. }
  359.  
  360. void CDialogTemplate::GetSizeInDialogUnits(SIZE* pSize) const
  361. {
  362.     ASSERT(m_hTemplate != NULL);
  363.     ASSERT_POINTER(pSize, SIZE);
  364.  
  365.     DLGTEMPLATE* pTemplate = (DLGTEMPLATE*)GlobalLock(m_hTemplate);
  366.  
  367.     if (IsDialogEx(pTemplate))
  368.     {
  369.         pSize->cx = ((DLGTEMPLATEEX*)pTemplate)->cx;
  370.         pSize->cy = ((DLGTEMPLATEEX*)pTemplate)->cy;
  371.     }
  372.     else
  373.     {
  374.         pSize->cx = pTemplate->cx;
  375.         pSize->cy = pTemplate->cy;
  376.     }
  377.  
  378.     GlobalUnlock(m_hTemplate);
  379. }
  380.  
  381. void CDialogTemplate::GetSizeInPixels(SIZE* pSize) const
  382. {
  383.     ASSERT(m_hTemplate != NULL);
  384.     ASSERT_POINTER(pSize, SIZE);
  385.  
  386.     if (m_bSystemFont)
  387.     {
  388.         GetSizeInDialogUnits(pSize);
  389.         DWORD dwDLU = GetDialogBaseUnits();
  390.         pSize->cx = (pSize->cx * LOWORD(dwDLU)) / 4;
  391.         pSize->cy = (pSize->cy * HIWORD(dwDLU)) / 8;
  392.     }
  393.     else
  394.     {
  395.         CString strFace;
  396.         WORD wSize;
  397.         GetFont(strFace, wSize);
  398.  
  399.         SIZE size;
  400.         GetSizeInDialogUnits(&size);
  401.         _AfxConvertDialogUnitsToPixels(strFace, wSize, size.cx, size.cy, pSize);
  402.     }
  403. }
  404.