Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

350 lines
10 KiB

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