XTPControlComboBoxExt.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:14k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTPControlComboBoxExt.cpp : implementation of the CXTPControlComboBoxExt class.
  2. //
  3. // This file is a part of the XTREME COMMANDBARS MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "Resource.h"
  22. #include "Common/XTPVC80Helpers.h"
  23. #include "Common/XTPResourceManager.h"
  24. #include "Common/XTPPropExchange.h"
  25. #include "XTPCommandBarsDefines.h"
  26. #include "XTPMouseManager.h"
  27. #include "XTPControlComboBox.h"
  28. #include "XTPControlComboBoxExt.h"
  29. #ifdef _DEBUG
  30. #undef THIS_FILE
  31. static char THIS_FILE[] = __FILE__;
  32. #define new DEBUG_NEW
  33. #endif
  34. #define XTP_FONTCOMBOSTYLE_DEFAULTCHARSETONLY 1
  35. // reserve lobyte for charset
  36. #define PRINTER_FONT 0x0100
  37. #define TT_FONT 0x0200
  38. #define DEVICE_FONT 0x0400
  39. #define MAX_POINT_SIZE 10
  40. static int nFontSizes[] =
  41. {8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72};
  42. static void OnCharFormatChanged(CHARFORMAT& cf, CXTPControl* pControl)
  43. {
  44. NMXTPCHARHDR fnm;
  45. fnm.cf = cf;
  46. pControl->NotifySite(XTP_FN_SETFORMAT, &fnm);
  47. }
  48. //////////////////////////////////////////////////////////////////////
  49. // Construction/Destruction
  50. //////////////////////////////////////////////////////////////////////
  51. IMPLEMENT_XTP_CONTROL(CXTPControlSizeComboBox, CXTPControlComboBox)
  52. CXTPControlSizeComboBox::CXTPControlSizeComboBox()
  53. {
  54. SetWidth(50);
  55. SetDropDownListStyle();
  56. m_nLogVert = 0;
  57. m_nTwipsLast = 0;
  58. }
  59. CXTPControlSizeComboBox::~CXTPControlSizeComboBox()
  60. {
  61. }
  62. BOOL CXTPControlSizeComboBox::OnSetPopup(BOOL bPopup)
  63. {
  64. if (bPopup && m_pCommandBar)
  65. {
  66. NMXTPCHARHDR fnm;
  67. fnm.cf.dwMask = 0;
  68. NotifySite(XTP_FN_GETFORMAT, &fnm);
  69. if ((fnm.cf.dwMask & (CFM_FACE | CFM_CHARSET)) == (CFM_FACE | CFM_CHARSET))
  70. {
  71. CString strFaceName = fnm.cf.szFaceName;
  72. CWindowDC dc(CWnd::GetDesktopWindow());
  73. EnumFontSizes(dc, strFaceName);
  74. }
  75. }
  76. return CXTPControlComboBox::OnSetPopup(bPopup);
  77. }
  78. void CXTPControlSizeComboBox::OnExecute()
  79. {
  80. int nSize = GetTwipSize();
  81. if (nSize == -2)
  82. {
  83. XTPResourceManager()->ShowMessageBox(XTP_IDS_INVALID_NUMBER, MB_OK | MB_ICONINFORMATION);
  84. }
  85. else if ((nSize >= 0 && nSize < 20) || nSize > 32760)
  86. {
  87. XTPResourceManager()->ShowMessageBox(XTP_IDS_INVALID_FONTSIZE, MB_OK | MB_ICONINFORMATION);
  88. }
  89. else if (nSize > 0)
  90. {
  91. CHARFORMAT cf;
  92. cf.cbSize = sizeof(CHARFORMAT);
  93. cf.dwMask = CFM_SIZE;
  94. cf.yHeight = nSize;
  95. OnCharFormatChanged(cf, this);
  96. }
  97. CXTPControlComboBox::OnExecute();
  98. }
  99. void CXTPControlSizeComboBox::EnumFontSizes(CDC& dc, LPCTSTR pFontName)
  100. {
  101. ResetContent();
  102. if (pFontName == NULL)
  103. return;
  104. if (pFontName[0] == NULL)
  105. return;
  106. ASSERT(dc.m_hDC != NULL);
  107. if (dc.m_hDC == NULL)
  108. return;
  109. m_nLogVert = dc.GetDeviceCaps(LOGPIXELSY);
  110. ::EnumFontFamilies(dc.m_hDC, pFontName,
  111. (FONTENUMPROC) EnumSizeCallBack, (LPARAM) this);
  112. }
  113. BOOL CALLBACK AFX_EXPORT CXTPControlSizeComboBox::EnumSizeCallBack(LOGFONT FAR* /*lplf*/,
  114. LPNEWTEXTMETRIC lpntm, int FontType, LPVOID lpv)
  115. {
  116. CXTPControlSizeComboBox* pThis = (CXTPControlSizeComboBox*)lpv;
  117. ASSERT(pThis != NULL);
  118. if (!pThis)
  119. return FALSE;
  120. TCHAR buf[MAX_POINT_SIZE];
  121. if (
  122. (FontType & TRUETYPE_FONTTYPE) ||
  123. !((FontType & TRUETYPE_FONTTYPE) || (FontType & RASTER_FONTTYPE))
  124. ) // if truetype or vector font
  125. {
  126. // this occurs when there is a truetype and nontruetype version of a font
  127. if (pThis->GetCount() != 0)
  128. pThis->ResetContent();
  129. for (int i = 0; i < 16; i++)
  130. {
  131. wsprintf(buf, _T("%d"), nFontSizes[i]);
  132. pThis->AddString(buf);
  133. }
  134. return FALSE; // don't call me again
  135. }
  136. // calc character height in pixels
  137. pThis->InsertSize(MulDiv(lpntm->tmHeight-lpntm->tmInternalLeading,
  138. 1440, pThis->m_nLogVert));
  139. return TRUE; // call me again
  140. }
  141. void CXTPControlSizeComboBox::InsertSize(int nSize)
  142. {
  143. ASSERT(nSize > 0);
  144. DWORD dwSize = (DWORD)nSize;
  145. CString strTwips = TwipsToPointString(nSize);
  146. if (FindStringExact(-1, strTwips) == CB_ERR)
  147. {
  148. int nIndex = -1;
  149. int nPos = 0;
  150. DWORD dw;
  151. while ((dw = (DWORD)GetItemData(nPos)) != (DWORD)CB_ERR)
  152. {
  153. if (dw > dwSize)
  154. {
  155. nIndex = nPos;
  156. break;
  157. }
  158. nPos++;
  159. }
  160. nIndex = InsertString(nIndex, strTwips);
  161. ASSERT(nIndex != CB_ERR);
  162. if (nIndex != CB_ERR)
  163. SetItemData(nIndex, dwSize);
  164. }
  165. }
  166. CString AFX_CDECL CXTPControlSizeComboBox::TwipsToPointString(int nTwips)
  167. {
  168. CString str;
  169. if (nTwips >= 0)
  170. {
  171. // round to nearest half point
  172. nTwips = (nTwips + 5) / 10;
  173. if ((nTwips % 2) == 0)
  174. str.Format(_T("%i"), nTwips / 2);
  175. else
  176. str.Format(_T("%.1f"), (float)nTwips / 2.0F);
  177. }
  178. return str;
  179. }
  180. int CXTPControlSizeComboBox::GetTwipSize() const
  181. {
  182. return GetTwipSize(GetEditText());
  183. }
  184. int CXTPControlSizeComboBox::GetTwipSize(LPCTSTR lpszText)
  185. {
  186. // return values
  187. // -2 -- error
  188. // -1 -- edit box empty
  189. // >= 0 -- font size in twips
  190. while (*lpszText == ' ' || *lpszText == 't')
  191. {
  192. lpszText++;
  193. }
  194. if (lpszText[0] == NULL)
  195. return -1; // no text in control
  196. double d = _tcstod(lpszText, (LPTSTR*)&lpszText);
  197. while (*lpszText == ' ' || *lpszText == 't')
  198. {
  199. lpszText++;
  200. }
  201. if (*lpszText != NULL)
  202. return -2;   // not terminated properly
  203. return (d < 0.) ? 0 : (int)(d * 20.);
  204. }
  205. void CXTPControlSizeComboBox::SetTwipSize(int nTwips)
  206. {
  207. if (HasFocus())
  208. return;
  209. if (nTwips != GetTwipSize())
  210. {
  211. SetEditText(TwipsToPointString(nTwips));
  212. }
  213. m_nTwipsLast = nTwips;
  214. }
  215. //////////////////////////////////////////////////////////////////////
  216. // CXTPControlFontComboBox Class
  217. //////////////////////////////////////////////////////////////////////
  218. CXTPControlFontComboBoxList::CFontDesc::CFontDesc(LPCTSTR lpszName, LPCTSTR lpszScript, BYTE nCharSet,
  219. BYTE nPitchAndFamily, DWORD dwFlags)
  220. {
  221. m_strName = lpszName;
  222. m_strScript = lpszScript;
  223. m_nCharSet = nCharSet;
  224. m_nPitchAndFamily = nPitchAndFamily;
  225. m_dwFlags = dwFlags;
  226. }
  227. void CXTPControlFontComboBoxList::CFontDescHolder::EnumFontFamilies()
  228. {
  229. if (m_arrayFontDesc.GetSize() == 0)
  230. {
  231. LOGFONT lf;
  232. memset(&lf, 0, sizeof(LOGFONT));
  233. lf.lfCharSet = DEFAULT_CHARSET;
  234. DWORD dwVersion = ::GetVersion();
  235. BOOL bWin4 = (BYTE)dwVersion >= 4;
  236. CWindowDC dc(CWnd::GetDesktopWindow());
  237. if (bWin4)
  238. {
  239. ::EnumFontFamiliesEx(dc, &lf,
  240. (FONTENUMPROC) EnumFamScreenCallBackEx, (LPARAM) this, NULL);
  241. }
  242. else
  243. {
  244. ::EnumFontFamilies(dc, NULL,
  245. (FONTENUMPROC) EnumFamScreenCallBack, (LPARAM) this);
  246. }
  247. }
  248. }
  249. void CXTPControlFontComboBoxList::CFontDescHolder::AddFont(ENUMLOGFONT* pelf, DWORD dwType, LPCTSTR lpszScript)
  250. {
  251. LOGFONT& lf = pelf->elfLogFont;
  252. if (lf.lfCharSet == MAC_CHARSET) // don't put in MAC fonts, commdlg doesn't either
  253. return;
  254. // Don't display vertical font for FE platform
  255. if ((lf.lfFaceName[0] == '@'))
  256. return;
  257. for (int i = 0; i < m_arrayFontDesc.GetSize(); i++)
  258. {
  259. CFontDesc* pDesc = (CFontDesc*)m_arrayFontDesc[i];
  260. if (pDesc->m_strName == lf.lfFaceName)
  261. return;
  262. }
  263. // don't put in non-printer raster fonts
  264. CFontDesc* pDesc = new CFontDesc(lf.lfFaceName, lpszScript,
  265. lf.lfCharSet, lf.lfPitchAndFamily, dwType);
  266. CString strName = lf.lfFaceName;
  267. int nIndex = 0;
  268. for (nIndex = 0; nIndex < m_arrayFontDesc.GetSize(); nIndex++)
  269. {
  270. if (strName < m_arrayFontDesc[nIndex]->m_strName)
  271. break;
  272. }
  273. m_arrayFontDesc.InsertAt(nIndex, pDesc);
  274. }
  275. BOOL CALLBACK AFX_EXPORT CXTPControlFontComboBoxList::CFontDescHolder::EnumFamScreenCallBack(ENUMLOGFONT* pelf,
  276. NEWTEXTMETRICEX* /*lpntm*/, int FontType, LPVOID pThis)
  277. {
  278. // don't put in non-printer raster fonts
  279. if (FontType & RASTER_FONTTYPE)
  280. return 1;
  281. DWORD dwData = (FontType & TRUETYPE_FONTTYPE) ? TT_FONT : 0;
  282. ((CXTPControlFontComboBoxList::CFontDescHolder *)pThis)->AddFont(pelf, dwData);
  283. return 1;
  284. }
  285. BOOL CALLBACK AFX_EXPORT CXTPControlFontComboBoxList::CFontDescHolder::EnumFamScreenCallBackEx(ENUMLOGFONTEX* pelf,
  286. NEWTEXTMETRICEX* /*lpntm*/, int FontType, LPVOID pThis)
  287. {
  288. // don't put in non-printer raster fonts
  289. if (FontType & RASTER_FONTTYPE)
  290. return 1;
  291. DWORD dwData = (FontType & TRUETYPE_FONTTYPE) ? TT_FONT : 0;
  292. ((CXTPControlFontComboBoxList::CFontDescHolder *)pThis)->AddFont((ENUMLOGFONT*)pelf, dwData, CString((TCHAR*)pelf->elfScript));
  293. return 1;
  294. }
  295. void CXTPControlFontComboBoxList::CreateListBox()
  296. {
  297. m_dwStyle |= LBS_SORT;
  298. CXTPControlComboBoxList::CreateListBox();
  299. }
  300. //////////////////////////////////////////////////////////////////////
  301. // Construction/Destruction
  302. //////////////////////////////////////////////////////////////////////
  303. IMPLEMENT_XTP_CONTROL(CXTPControlFontComboBox, CXTPControlComboBox)
  304. CXTPControlFontComboBox::CXTPControlFontComboBox(DWORD dwStyleListBox)
  305. {
  306. if (m_pCommandBar)
  307. {
  308. m_pCommandBar->InternalRelease();
  309. }
  310. m_pCommandBar = new CXTPControlFontComboBoxList();
  311. ((CXTPControlFontComboBoxList*)m_pCommandBar)->CreateListBox();
  312. ((CXTPControlFontComboBoxList*)m_pCommandBar)->EnumFontFamiliesEx(dwStyleListBox);
  313. SetWidth(150);
  314. SetDropDownWidth(250);
  315. SetDropDownListStyle();
  316. m_bAutoComplete = TRUE;
  317. }
  318. CXTPControlFontComboBox::~CXTPControlFontComboBox()
  319. {
  320. }
  321. void CXTPControlFontComboBox::OnExecute()
  322. {
  323. CHARFORMAT cf;
  324. cf.cbSize = sizeof(CHARFORMAT);
  325. cf.szFaceName[0] = NULL;
  326. // this will retrieve the font entered in the edit control
  327. // it tries to match the font to something already present in the combo box
  328. // this effectively ignores case of a font the user enters
  329. // if a user enters arial, this will cause it to become Arial
  330. CString str = GetEditText();
  331. // if font name box is not empty
  332. if (!str.IsEmpty())
  333. {
  334. cf.dwMask = CFM_FACE | CFM_CHARSET;
  335. int nIndex = FindStringExact(-1, str);
  336. if (nIndex != CB_ERR)
  337. {
  338. CXTPControlFontComboBoxList::CFontDesc* pDesc = (CXTPControlFontComboBoxList::CFontDesc*)GetItemData(nIndex);
  339. ASSERT(pDesc != NULL);
  340. if (!pDesc)
  341. return;
  342. ASSERT(pDesc->m_strName.GetLength() < LF_FACESIZE);
  343. #if (_RICHEDIT_VER >= 0x0200)
  344. lstrcpyn(cf.szFaceName, pDesc->m_strName, LF_FACESIZE);
  345. #else
  346. lstrcpynA(cf.szFaceName, XTP_CT2CA(pDesc->m_strName), LF_FACESIZE);
  347. #endif
  348. cf.bCharSet = pDesc->m_nCharSet;
  349. cf.bPitchAndFamily = pDesc->m_nPitchAndFamily;
  350. }
  351. else // unknown font
  352. {
  353. ASSERT(str.GetLength() < LF_FACESIZE);
  354. #if (_RICHEDIT_VER >= 0x0200)
  355. lstrcpyn(cf.szFaceName, str, LF_FACESIZE);
  356. #else
  357. lstrcpynA(cf.szFaceName, XTP_CT2CA(str), LF_FACESIZE);
  358. #endif
  359. cf.bCharSet = DEFAULT_CHARSET;
  360. cf.bPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
  361. }
  362. OnCharFormatChanged(cf, this);
  363. }
  364. CXTPControlComboBox::OnExecute();
  365. }
  366. void CXTPControlFontComboBox::SetCharFormat(CHARFORMAT& cf)
  367. {
  368. if (HasFocus())
  369. return;
  370. // the selection must be same font and charset to display correctly
  371. if ((cf.dwMask & (CFM_FACE | CFM_CHARSET)) == (CFM_FACE | CFM_CHARSET))
  372. SetEditText(CString(cf.szFaceName));
  373. else
  374. SetEditText(_T(""));
  375. }
  376. void CXTPControlFontComboBoxList::EnumFontFamiliesEx(BOOL dwStyleListBox)
  377. {
  378. m_dwStyleListBox = dwStyleListBox;
  379. CMapStringToPtr map;
  380. ((CListBox*)this)->ResetContent();
  381. static CXTPControlFontComboBoxList::CFontDescHolder s_fontHolder;
  382. s_fontHolder.EnumFontFamilies();
  383. // now walk through the fonts and remove (charset) from fonts with only one
  384. CArray<CFontDesc*, CFontDesc*>& arrFontDesc = s_fontHolder.m_arrayFontDesc;
  385. int nCount = (int)arrFontDesc.GetSize();
  386. int i;
  387. // walk through fonts adding names to string map
  388. // first time add value 0, after that add value 1
  389. for (i = 0; i < nCount; i++)
  390. {
  391. CFontDesc* pDesc = arrFontDesc[i];
  392. void* pv = NULL;
  393. if (map.Lookup(pDesc->m_strName, pv)) // found it
  394. {
  395. if (pv == NULL) // only one entry so far
  396. {
  397. map.RemoveKey(pDesc->m_strName);
  398. map.SetAt(pDesc->m_strName, (void*)1);
  399. }
  400. }
  401. else // not found
  402. map.SetAt(pDesc->m_strName, (void*)0);
  403. }
  404. for (i = 0; i < nCount; i++)
  405. {
  406. CFontDesc* pDesc = arrFontDesc[i];
  407. CString str = pDesc->m_strName;
  408. void* pv = NULL;
  409. VERIFY(map.Lookup(str, pv));
  410. if (pv != NULL && !pDesc->m_strScript.IsEmpty())
  411. {
  412. str += " (";
  413. str += pDesc->m_strScript;
  414. str += ")";
  415. }
  416. int nIndex = ((CListBox*)this)->AddString(str);
  417. ASSERT(nIndex >= 0);
  418. if (nIndex >= 0) //no error
  419. ((CListBox*)this)->SetItemDataPtr(nIndex, pDesc);
  420. }
  421. }
  422. IMPLEMENT_XTP_COMMANDBAR(CXTPControlFontComboBoxList, CXTPControlComboBoxList)
  423. void CXTPControlFontComboBoxList::Copy(CXTPCommandBar* pCommandBar, BOOL bRecursive)
  424. {
  425. CXTPPopupBar::Copy(pCommandBar, bRecursive);
  426. ASSERT(pCommandBar->IsKindOf(RUNTIME_CLASS(CXTPControlFontComboBoxList)));
  427. m_dwStyleListBox = ((CXTPControlFontComboBoxList*)pCommandBar)->m_dwStyleListBox;
  428. if (!m_hWnd)
  429. CreateListBox();
  430. EnumFontFamiliesEx(m_dwStyleListBox);
  431. }
  432. void CXTPControlFontComboBoxList::DoPropExchange(CXTPPropExchange* pPX)
  433. {
  434. CXTPPopupBar::DoPropExchange(pPX);
  435. PX_DWord(pPX, _T("StyleListBox"), m_dwStyleListBox, XTP_FONTCOMBOSTYLE_DEFAULTCHARSETONLY);
  436. if (pPX->IsLoading())
  437. {
  438. if (!m_hWnd)
  439. CreateListBox();
  440. EnumFontFamiliesEx(m_dwStyleListBox);
  441. }
  442. }