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