dlgcset.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 11k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //
  2. // File: dlgcset.cpp
  3. //
  4. // This file contains the code that implements CNativeFont class.
  5. //
  6. // history:
  7. //     7-21-97 created; 
  8. // 
  9. #include "ctlspriv.h"
  10. #include "ccontrol.h"
  11. #define THISCLASS CNativeFont
  12. #define SUPERCLASS CControl
  13. typedef enum 
  14. {
  15.     FAS_NOTINITIALIZED = 0,
  16.     FAS_DISABLED,
  17.     FAS_ENABLED,
  18. } FASTATUS;
  19. class CNativeFont : public CControl
  20. {
  21. public:
  22.     //Function Memebers
  23.     virtual LRESULT v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  24.     static LRESULT NativeFontWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  25.     
  26. protected:
  27.     
  28.     CNativeFont();
  29.     
  30.     //Function Members    
  31.     virtual void v_OnPaint(HDC hdc) ;
  32.     virtual LRESULT v_OnCreate();
  33.     virtual void v_OnSize(int x, int y)  {};
  34.     virtual LRESULT v_OnCommand(WPARAM wParam, LPARAM lParam);
  35.     virtual LRESULT v_OnNotify(WPARAM wParam, LPARAM lParam);
  36.     virtual DWORD v_OnStyleChanged(WPARAM wParam, LPARAM lParam) { return 0; };    
  37.     
  38.     HRESULT _GetNativeDialogFont(HWND hDlg);
  39.     static HRESULT _GetFontAssocStatus(FASTATUS  *uiAssoced);
  40.     static BOOL _SetFontEnumProc(HWND hwnd, LPARAM lparam);
  41.     static LRESULT _SubclassDlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam, WPARAM uIdSubclass, ULONG_PTR dwRefData);
  42.     HFONT   m_hfontOrg;
  43.     HFONT   m_hfontNative;
  44.     HFONT   m_hfontDelete;
  45.     typedef struct {
  46.                 HFONT hfontSet;
  47.                 DWORD dwStyle;
  48.             } NFENUMCHILDDATA;
  49.     static FASTATUS _s_uiFontAssocStatus;
  50. };
  51. // static variable initialization
  52. FASTATUS CNativeFont::_s_uiFontAssocStatus = FAS_NOTINITIALIZED;
  53. // reg keys
  54. static const TCHAR s_szRegFASettings[] = TEXT("System\CurrentControlSet\Control\FontAssoc\Associated Charset");
  55. CNativeFont::CNativeFont(void)
  56. {
  57.     m_hfontOrg = NULL;
  58.     m_hfontNative = NULL;
  59.     m_hfontDelete = NULL;
  60. }
  61. LRESULT THISCLASS::NativeFontWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  62. {
  63.     CNativeFont *pn = (CNativeFont *)GetWindowLongPtr(hwnd, 0);
  64.     if (uMsg == WM_CREATE) {
  65.         ASSERT(!pn);
  66.         pn = new CNativeFont();
  67.         if (!pn)
  68.             return 0L;
  69.     } 
  70.     if (pn) {
  71.         return pn->v_WndProc(hwnd, uMsg, wParam, lParam);
  72.     }
  73.     return DefWindowProc(hwnd, uMsg, wParam, lParam);
  74. }
  75. void THISCLASS::v_OnPaint(HDC hdc)
  76. {
  77.     return;
  78. }
  79. LRESULT THISCLASS::v_OnCommand(WPARAM wParam, LPARAM lParam)
  80. {
  81.     // forward to parent (do we really need this?)
  82.     return SendMessage(ci.hwndParent, WM_COMMAND, wParam, lParam);
  83. }
  84. LRESULT THISCLASS::v_OnNotify(WPARAM wParam, LPARAM lParam)
  85. {
  86.     // forward to parent
  87.     LPNMHDR lpNmhdr = (LPNMHDR)lParam;
  88.     
  89.     return SendNotifyEx(ci.hwndParent, (HWND) -1,
  90.                          lpNmhdr->code, lpNmhdr, ci.bUnicode);
  91. }
  92. LRESULT THISCLASS::v_OnCreate()
  93. {
  94.     return TRUE;
  95. }
  96. BOOL THISCLASS::_SetFontEnumProc(HWND hwnd, LPARAM lparam)
  97. {
  98.      NFENUMCHILDDATA *  pdt = (NFENUMCHILDDATA *)lparam; 
  99.      BOOL bMatch = FALSE;
  100.      
  101.      if (pdt && pdt->hfontSet)
  102.      {
  103.          if (pdt->dwStyle & NFS_ALL)
  104.          {
  105.              bMatch = TRUE;
  106.          }
  107.          else
  108.          {
  109.              TCHAR szClass[32];
  110.              
  111.              GetClassName(hwnd, szClass, ARRAYSIZE(szClass));
  112.              
  113.              if (pdt->dwStyle & NFS_EDIT)
  114.              {
  115.                  bMatch |= (lstrcmpi(TEXT("Edit"), szClass) == 0);
  116.                  bMatch |= (lstrcmpi(TEXT("RichEdit20A"), szClass) == 0);
  117.                  bMatch |= (lstrcmpi(TEXT("RichEdit20W"), szClass) == 0);
  118.              }
  119.              
  120.              if (pdt->dwStyle & NFS_STATIC)
  121.                  bMatch |= (lstrcmpi(TEXT("Static"), szClass) == 0);
  122.              
  123.              if (pdt->dwStyle & NFS_BUTTON)
  124.                  bMatch |= (lstrcmpi(TEXT("Button"), szClass) == 0);
  125.              if (pdt->dwStyle & NFS_LISTCOMBO)
  126.              {
  127.                  bMatch |= (lstrcmpi(TEXT("ListBox"), szClass) == 0);
  128.                  bMatch |= (lstrcmpi(TEXT("ComboBox"), szClass) == 0);
  129.                  bMatch |= (lstrcmpi(TEXT("ComboBoxEx32"), szClass) == 0);
  130.                  bMatch |= (lstrcmpi(TEXT("SysListView32"), szClass) == 0);
  131.              }
  132.          }
  133.          if (bMatch) 
  134.              SendMessage(hwnd, WM_SETFONT, (WPARAM)pdt->hfontSet, MAKELPARAM(FALSE, 0));
  135.          return TRUE;
  136.      }
  137.      else
  138.          return FALSE;
  139. }
  140. LRESULT THISCLASS::_SubclassDlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam, WPARAM uIdSubclass, ULONG_PTR dwRefData)
  141. {
  142.     LRESULT lret = 0;
  143.     CNativeFont * pnf = (CNativeFont *)dwRefData;
  144.     
  145.     if (pnf)
  146.     {
  147.     
  148.         switch (uMsg)
  149.         {
  150.             case WM_INITDIALOG:
  151.                 // we enumerate its children so they get font 
  152.                 // in native charset selected if necessary
  153.                 // 
  154.                 if (S_OK == pnf->_GetNativeDialogFont(hdlg))
  155.                 {
  156.                     // S_OK means we have different charset from 
  157.                     // the default of the platform on which we're 
  158.                     // running.
  159.                     NFENUMCHILDDATA dt;
  160.                     dt.hfontSet = pnf->m_hfontNative;
  161.                     dt.dwStyle = pnf->ci.style;
  162.                     EnumChildWindows(hdlg, (WNDENUMPROC)pnf->_SetFontEnumProc, (LPARAM)&dt);
  163.                 }
  164.                 // we no longer need subclass procedure.
  165.                 // assumes no one has subclassed this dialog by now
  166.                 break;
  167.             case WM_DESTROY:
  168.                 // if we've created a font, we have to clean it up.
  169.                 if (pnf->m_hfontDelete)
  170.                 {
  171.                     NFENUMCHILDDATA dt;
  172.                 
  173.                     dt.hfontSet = pnf->m_hfontOrg;
  174.                     dt.dwStyle = pnf->ci.style;
  175.                     // just in case anyone is still alive
  176.                     EnumChildWindows(hdlg, (WNDENUMPROC)pnf->_SetFontEnumProc, (LPARAM)&dt);
  177.                     DeleteObject(pnf->m_hfontDelete);
  178.                     pnf->m_hfontDelete = NULL;
  179.                 }
  180.                 RemoveWindowSubclass(hdlg, pnf->_SubclassDlgProc, 0);
  181.                 break;
  182.         }
  183.     
  184.         lret = DefSubclassProc(hdlg, uMsg, wParam, lParam);
  185.     }
  186.  
  187.     return lret;
  188. }
  189. LRESULT THISCLASS::v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  190. {
  191.     HWND hdlg;
  192.     
  193.     switch (uMsg)
  194.     {
  195.         case WM_CREATE:
  196.         // subclass the parent dialog just to get notified for WM_INITDIALOG
  197.             hdlg = GetParent(hwnd);
  198.             if (hdlg)
  199.             {
  200.                 // if we had an error just do nothing, we have to succeed in creating
  201.                 // window anyway otherwise dialog fails.
  202.                 SetWindowSubclass(hdlg, _SubclassDlgProc, 0, (ULONG_PTR)this);
  203.             }
  204.             break;
  205.     }
  206.     return SUPERCLASS::v_WndProc(hwnd, uMsg, wParam, lParam);
  207. }
  208. // _GetNativeDialogFont
  209. //
  210. // Retreive font handle in platform native character set
  211. //
  212. // returns S_OK if the given dialogbox requires setting font
  213. //              in native charset
  214. //         S_FALSE if the given dialogbox already has native
  215. //              charset.
  216. //         E_FAIL if anyother error occurs
  217. //
  218. HRESULT THISCLASS::_GetNativeDialogFont(HWND hDlg)
  219. {
  220.     HRESULT hres = E_FAIL;
  221.     
  222.     if(!m_hfontNative)
  223.     {
  224.         HFONT hfontNative, hfont = GetWindowFont(hDlg);
  225.         LOGFONT lf, lfNative;
  226.         FASTATUS uiFAStat = FAS_NOTINITIALIZED;
  227.         GetObject(hfont, sizeof(LOGFONT), &lf);
  228.         SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lfNative, 0);
  229.         
  230.         // there are two cases we don't want to create/set font
  231.         // for the platform native character set.
  232.         // 1) we already have matching character set
  233.         // 2) the platform has 'font assoc' enabled or 'font link'
  234.         //    and our client wants to use it instead of
  235.         //    setting the right character set. (NFS_USEFONTASSOC)
  236.         //    this solution sometimes provides better
  237.         //    appearance (thought it is broken in its 
  238.         //    font metrics) because it would use 
  239.         //    'western font' as is.
  240.         if (ci.style & NFS_USEFONTASSOC)
  241.         {
  242.             _GetFontAssocStatus(&uiFAStat);
  243.         }
  244.         if ( uiFAStat == FAS_ENABLED
  245.            || lfNative.lfCharSet == lf.lfCharSet)
  246.         {
  247.                 
  248.             m_hfontOrg = m_hfontNative = hfont;
  249.         }
  250.         else
  251.         {
  252.             // we have non-native charset for the platform
  253.             // Save away the original font first.
  254.             m_hfontOrg = hfont;
  255.             
  256.             // Use the height of original dialog font
  257.             lfNative.lfHeight = lf.lfHeight;
  258.             if (!(hfontNative=CreateFontIndirect(&lfNative)))
  259.             {
  260.                 hfontNative = hfont;
  261.             }
  262.             // save it away so we can delete it later
  263.             if (hfontNative != hfont)
  264.                 m_hfontDelete = hfont;
  265.         
  266.             // set this variable to avoid calling createfont twice
  267.             // if we get called again.
  268.             m_hfontNative = hfontNative;
  269.         }
  270.     }
  271.     return hres = (m_hfontNative == m_hfontOrg ? S_FALSE : S_OK);
  272. }
  273. //
  274. // _GetFontAssocStatus
  275. //
  276. // synopsis: check to see if the platform has "Font Association"
  277. //           enabled or 'Font Link' capability
  278. //
  279. HRESULT THISCLASS::_GetFontAssocStatus(FASTATUS  *puiAssoced)
  280. {
  281.     HRESULT hr = S_OK;
  282.     ASSERT(puiAssoced);
  283.     
  284.     // I assume the setting won't change without rebooting
  285.     // the system
  286.     //
  287.     if (FAS_NOTINITIALIZED == _s_uiFontAssocStatus)
  288.     {
  289.         if (g_bRunOnNT5)
  290.         {
  291.             // NT5 has fontlink functionality
  292.             _s_uiFontAssocStatus = FAS_ENABLED;
  293.         }
  294.         else
  295.         {
  296.             HKEY hkey;
  297.             TCHAR szYesOrNo[16] = {0};
  298.             if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
  299.                               s_szRegFASettings,
  300.                              0, KEY_READ, &hkey) == ERROR_SUCCESS) 
  301.             {
  302.                 DWORD dwSize = sizeof(szYesOrNo);
  303.                 RegQueryValueEx(hkey, TEXT("ANSI(00)"), 0, NULL, (LPBYTE)szYesOrNo, &dwSize);
  304.                 RegCloseKey(hkey);
  305.             }
  306.             else
  307.             {
  308.                 // this only indicates the reg func failed
  309.                 // we can't always assume the key is there (Western)
  310.                 //
  311.                 hr = S_FALSE; 
  312.             }
  313.         
  314.             if (SUCCEEDED(hr) && !lstrcmpi(szYesOrNo, TEXT("yes")))
  315.             {
  316.                 // font assoc is enabled
  317.                 _s_uiFontAssocStatus = FAS_ENABLED;
  318.             }
  319.             else
  320.                 _s_uiFontAssocStatus = FAS_DISABLED;
  321.         }
  322.     }
  323.     *puiAssoced = _s_uiFontAssocStatus;
  324.     return hr;
  325. }
  326. extern "C" {
  327.     
  328. BOOL InitNativeFontCtl(HINSTANCE hinst)
  329. {
  330.     WNDCLASS wc;
  331.     if (!GetClassInfo(hinst, WC_NATIVEFONTCTL, &wc)) {
  332.         wc.lpfnWndProc     = THISCLASS::NativeFontWndProc;
  333.         wc.hCursor         = LoadCursor(NULL, IDC_ARROW);
  334.         wc.hIcon           = NULL;
  335.         wc.lpszMenuName    = NULL;
  336.         wc.hInstance       = hinst;
  337.         wc.lpszClassName   = WC_NATIVEFONTCTL;
  338.         wc.hbrBackground   = (HBRUSH)(COLOR_BTNFACE + 1); // NULL;
  339.         wc.style           = CS_GLOBALCLASS;
  340.         wc.cbWndExtra      = sizeof(LPVOID);
  341.         wc.cbClsExtra      = 0;
  342.         return RegisterClass(&wc);
  343.     }
  344.     return TRUE;
  345. }
  346. };