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.

594 lines
13 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. colefont.cpp
  5. Abstract:
  6. Font class.
  7. --*/
  8. #include "polyline.h"
  9. #include "utils.h"
  10. #include "smonctrl.h"
  11. #include "unihelpr.h"
  12. #include "COleFont.h"
  13. #pragma warning ( disable : 4355 ) // "this" used in initializer list
  14. const LPWSTR COleFont::m_cwszDefaultFaceName = L"MS Shell Dlg";
  15. const INT COleFont::m_iDefaultTmHeight = 13;
  16. const SHORT COleFont::m_iDefaultTmWeight = 400;
  17. const INT COleFont::m_iDefaultRiPxlsPerInch = 96;
  18. COleFont::COleFont (
  19. CSysmonControl *pCtrl
  20. )
  21. : m_NotifySink( this )
  22. {
  23. m_pIFont = NULL;
  24. m_pIFontBold = NULL;
  25. m_pCtrl = pCtrl;
  26. m_pIConnPt = NULL;
  27. }
  28. #pragma warning ( default : 4355 ) // "this" used in initializer list
  29. COleFont::~COleFont (
  30. void
  31. )
  32. {
  33. // Release current connection point
  34. if (m_pIConnPt) {
  35. m_pIConnPt->Unadvise(m_dwCookie);
  36. ReleaseInterface(m_pIConnPt);
  37. }
  38. // Release fonts
  39. ReleaseInterface(m_pIFont);
  40. ReleaseInterface(m_pIFontBold);
  41. return;
  42. }
  43. void
  44. COleFont::InitDefaultFontDesc (
  45. FONTDESC& rFontDesc,
  46. INT& riPxlsPerInch,
  47. WCHAR achFaceName[LF_FACESIZE+1])
  48. {
  49. TEXTMETRIC TextMetrics;
  50. HFONT hFontOld;
  51. HDC hDC;
  52. USES_CONVERSION
  53. // Todo: Must define proper default values, move them to resources
  54. // for localization.
  55. ZeroMemory ( &rFontDesc, sizeof ( FONTDESC ) );
  56. // Select default font
  57. hDC = GetDC(NULL);
  58. if ( NULL != hDC ) {
  59. hFontOld = SelectFont(hDC, (HFONT)GetStockObject(DEFAULT_GUI_FONT));
  60. // Get face name and size
  61. GetTextMetrics(hDC, &TextMetrics);
  62. GetTextFaceW(hDC, LF_FACESIZE, achFaceName);
  63. // Get pixels per inch
  64. riPxlsPerInch = GetDeviceCaps(hDC, LOGPIXELSY);
  65. // Create a default font
  66. rFontDesc.lpstrName = achFaceName;
  67. rFontDesc.cySize.int64 = ((TextMetrics.tmHeight * 72) / riPxlsPerInch) * 10000;
  68. rFontDesc.sWeight = (short)TextMetrics.tmWeight;
  69. SelectFont(hDC, hFontOld);
  70. ReleaseDC(NULL, hDC);
  71. } else {
  72. riPxlsPerInch = m_iDefaultRiPxlsPerInch;
  73. lstrcpyW ( achFaceName, m_cwszDefaultFaceName );
  74. // Create a default font
  75. rFontDesc.lpstrName = achFaceName;
  76. rFontDesc.cySize.int64 = ((m_iDefaultTmHeight * 72) / m_iDefaultRiPxlsPerInch) * 10000;
  77. rFontDesc.sWeight = m_iDefaultTmWeight;
  78. }
  79. rFontDesc.cbSizeofstruct = sizeof(rFontDesc);
  80. rFontDesc.sCharset = DEFAULT_CHARSET;
  81. rFontDesc.fItalic = 0;
  82. rFontDesc.fUnderline = 0;
  83. rFontDesc.fStrikethrough = 0;
  84. return;
  85. }
  86. HRESULT COleFont::Init (
  87. VOID
  88. )
  89. {
  90. HRESULT hr;
  91. FONTDESC fontDesc;
  92. WCHAR achFontFaceName[LF_FACESIZE+1];
  93. LPFONT pIFont;
  94. INT iPxlsPerInch;
  95. InitDefaultFontDesc ( fontDesc, iPxlsPerInch, achFontFaceName );
  96. hr = OleCreateFontIndirect(&fontDesc, IID_IFont, (void**)&pIFont);
  97. if (FAILED(hr))
  98. return hr;
  99. pIFont->SetRatio(iPxlsPerInch, HIMETRIC_PER_INCH);
  100. hr = SetIFont(pIFont);
  101. pIFont->Release();
  102. return hr;
  103. }
  104. STDMETHODIMP COleFont::SetIFont(
  105. LPFONT pIFont
  106. )
  107. {
  108. HRESULT hr;
  109. IConnectionPointContainer *pIConnPtCont;
  110. IPropertyNotifySink *pISink;
  111. // Release current connection point
  112. if (m_pIConnPt) {
  113. m_pIConnPt->Unadvise(m_dwCookie);
  114. ReleaseInterface(m_pIConnPt);
  115. }
  116. // Release current fonts
  117. ReleaseInterface(m_pIFont);
  118. ReleaseInterface(m_pIFontBold);
  119. // Addref and hold new IFont
  120. m_pIFont = pIFont;
  121. m_pIFont->AddRef();
  122. // Get it's property notify connection point
  123. hr = pIFont->QueryInterface(IID_IConnectionPointContainer, (void **)&pIConnPtCont);
  124. if (SUCCEEDED(hr)) {
  125. hr = pIConnPtCont->FindConnectionPoint(IID_IPropertyNotifySink, &m_pIConnPt);
  126. pIConnPtCont->Release();
  127. // Connect our sink to it
  128. if (SUCCEEDED(hr)) {
  129. m_NotifySink.QueryInterface(IID_IPropertyNotifySink, (void **)&pISink);
  130. hr = m_pIConnPt->Advise(pISink, &m_dwCookie);
  131. }
  132. }
  133. // Force a change notification
  134. FontChange(DISPID_UNKNOWN);
  135. return hr;
  136. }
  137. void
  138. COleFont::FontChange (
  139. DISPID DispId
  140. )
  141. {
  142. CY size;
  143. BOOL bool;
  144. short weight;
  145. BSTR bstrName;
  146. // if not bold font, force clone of normal font
  147. if (m_pIFontBold == NULL)
  148. DispId = DISPID_UNKNOWN;
  149. // Copy changed parameter to bold font
  150. switch (DispId) {
  151. case DISPID_FONT_NAME:
  152. if (SUCCEEDED(m_pIFont->get_Name(&bstrName))) {
  153. m_pIFontBold->put_Name(bstrName);
  154. SysFreeString(bstrName);
  155. }
  156. break;
  157. case DISPID_FONT_SIZE:
  158. m_pIFont->get_Size(&size);
  159. m_pIFontBold->put_Size(size);
  160. break;
  161. case DISPID_FONT_ITALIC:
  162. m_pIFont->get_Italic(&bool);
  163. m_pIFontBold->put_Italic(bool);
  164. break;
  165. case DISPID_FONT_UNDER:
  166. m_pIFont->get_Underline(&bool);
  167. m_pIFontBold->put_Underline(bool);
  168. break;
  169. case DISPID_FONT_STRIKE:
  170. m_pIFont->get_Strikethrough(&bool);
  171. m_pIFontBold->put_Strikethrough(bool);
  172. break;
  173. case DISPID_FONT_WEIGHT:
  174. m_pIFont->get_Weight(&weight);
  175. m_pIFontBold->put_Weight(weight);
  176. m_pIFontBold->put_Bold(TRUE);
  177. break;
  178. case DISPID_UNKNOWN:
  179. ReleaseInterface(m_pIFontBold);
  180. if (SUCCEEDED(m_pIFont->Clone(&m_pIFontBold))) {
  181. m_pIFontBold->put_Bold(TRUE);
  182. }
  183. }
  184. // Notify owner of font change
  185. m_pCtrl->FontChanged();
  186. }
  187. STDMETHODIMP COleFont::GetFontDisp (
  188. OUT IFontDisp **ppFont
  189. )
  190. {
  191. *ppFont = NULL;
  192. if (m_pIFont == NULL)
  193. return E_UNEXPECTED;
  194. return m_pIFont->QueryInterface(IID_IFontDisp, (void **)ppFont);
  195. }
  196. STDMETHODIMP COleFont::GetHFont (
  197. OUT HFONT *phFont
  198. )
  199. {
  200. if ( m_pIFont == NULL ) {
  201. *phFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  202. } else {
  203. if ( FAILED(m_pIFont->get_hFont(phFont)) ) {
  204. *phFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  205. }
  206. }
  207. return S_OK;
  208. }
  209. STDMETHODIMP COleFont::GetHFontBold (
  210. OUT HFONT *phFont
  211. )
  212. {
  213. if (m_pIFontBold == NULL ) {
  214. *phFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  215. } else {
  216. if ( FAILED(m_pIFontBold->get_hFont(phFont)) ) {
  217. *phFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  218. }
  219. }
  220. return S_OK;
  221. }
  222. STDMETHODIMP COleFont::LoadFromStream (
  223. LPSTREAM pIStream
  224. )
  225. {
  226. HRESULT hr;
  227. IPersistStream *pIPersist = NULL;
  228. FONTDESC fontDesc;
  229. WCHAR achFontFaceName[LF_FACESIZE+1];
  230. LPFONT pIFont = NULL;
  231. INT iPxlsPerInch;
  232. if (m_pIFont == NULL)
  233. return E_FAIL;
  234. // Calling pIPersist for the existing font seems to miss some
  235. // important notification, so create a new font, load properties
  236. // from the stream, and replace the current font.
  237. InitDefaultFontDesc ( fontDesc, iPxlsPerInch, achFontFaceName );
  238. hr = OleCreateFontIndirect(&fontDesc, IID_IFont, (void**)&pIFont);
  239. if (FAILED(hr))
  240. return hr;
  241. pIFont->SetRatio(iPxlsPerInch, HIMETRIC_PER_INCH);
  242. hr = pIFont->QueryInterface(IID_IPersistStream, (void **)&pIPersist);
  243. if (SUCCEEDED(hr)) {
  244. hr = pIPersist->Load(pIStream);
  245. pIPersist->Release();
  246. hr = SetIFont(pIFont);
  247. }
  248. pIFont->Release();
  249. return hr;
  250. }
  251. STDMETHODIMP COleFont::SaveToStream (
  252. LPSTREAM pIStream,
  253. BOOL fClearDirty
  254. )
  255. {
  256. IPersistStream *pIPersist;
  257. HRESULT hr;
  258. if (m_pIFont == NULL)
  259. return E_FAIL;
  260. hr = m_pIFont->QueryInterface(IID_IPersistStream, (void **)&pIPersist);
  261. if (SUCCEEDED(hr)) {
  262. hr = pIPersist->Save(pIStream, fClearDirty);
  263. pIPersist->Release();
  264. }
  265. return hr;
  266. }
  267. HRESULT
  268. COleFont::LoadFromPropertyBag (
  269. IPropertyBag* pIPropBag,
  270. IErrorLog* pIErrorLog )
  271. {
  272. HRESULT hr = S_OK;
  273. WCHAR achFontFaceName[LF_FACESIZE+1];
  274. WCHAR achPropBagFaceName[LF_FACESIZE+1];
  275. INT iBufSize = LF_FACESIZE+1;
  276. FONTDESC fontDesc;
  277. LPFONT pIFont;
  278. VARIANT vValue;
  279. BOOL bValue;
  280. SHORT iValue;
  281. CY cySize;
  282. INT iPxlsPerInch;
  283. if (m_pIFont == NULL)
  284. return E_FAIL;
  285. InitDefaultFontDesc ( fontDesc, iPxlsPerInch, achFontFaceName );
  286. hr = StringFromPropertyBag (
  287. pIPropBag,
  288. pIErrorLog,
  289. L"FontName",
  290. achPropBagFaceName,
  291. iBufSize );
  292. if ( SUCCEEDED( hr ) ) {
  293. fontDesc.lpstrName = T2W(achPropBagFaceName);
  294. }
  295. hr = CyFromPropertyBag ( pIPropBag, pIErrorLog, L"FontSize", cySize );
  296. if ( SUCCEEDED( hr ) ){
  297. fontDesc.cySize.int64 = cySize.int64;
  298. }
  299. hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, L"FontItalic", bValue );
  300. if ( SUCCEEDED( hr ) ){
  301. fontDesc.fItalic = ( 0 == bValue ? 0 : 1 );
  302. }
  303. hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, L"FontUnderline", bValue );
  304. if ( SUCCEEDED( hr ) ){
  305. fontDesc.fUnderline = ( 0 == bValue ? 0 : 1 );
  306. }
  307. hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, L"FontStrikethrough", bValue );
  308. if ( SUCCEEDED( hr ) ){
  309. fontDesc.fStrikethrough = ( 0 == bValue ? 0 : 1 );
  310. }
  311. hr = ShortFromPropertyBag ( pIPropBag, pIErrorLog, L"FontWeight", iValue );
  312. if ( SUCCEEDED( hr ) ){
  313. fontDesc.sWeight = iValue;
  314. }
  315. hr = OleCreateFontIndirect(&fontDesc, IID_IFont, (void**)&pIFont);
  316. if (FAILED(hr))
  317. return hr;
  318. // pIFont->SetRatio(iPxlsPerInch, HIMETRIC_PER_INCH);
  319. hr = SetIFont(pIFont);
  320. pIFont->Release();
  321. VariantClear ( &vValue );
  322. return hr;
  323. }
  324. HRESULT
  325. COleFont::SaveToPropertyBag (
  326. IPropertyBag* pIPropBag,
  327. BOOL /* fClearDirty */,
  328. BOOL /* fSaveAllProps */ )
  329. {
  330. HRESULT hr = NOERROR;
  331. VARIANT vValue;
  332. BOOL bValue;
  333. if (m_pIFont == NULL)
  334. return E_FAIL;
  335. VariantInit( &vValue );
  336. vValue.vt = VT_BSTR;
  337. hr = m_pIFont->get_Name( &vValue.bstrVal);
  338. if ( SUCCEEDED( hr ) ) {
  339. hr = pIPropBag->Write(L"FontName", &vValue );
  340. VariantClear ( &vValue );
  341. }
  342. if ( SUCCEEDED( hr ) ) {
  343. if ( SUCCEEDED( hr ) ){
  344. CY cySize;
  345. hr = m_pIFont->get_Size ( &cySize );
  346. if ( SUCCEEDED( hr ) ) {
  347. hr = CyToPropertyBag ( pIPropBag, L"FontSize", cySize );
  348. }
  349. }
  350. }
  351. if ( SUCCEEDED( hr ) ) {
  352. if ( SUCCEEDED( hr ) ){
  353. hr = m_pIFont->get_Italic ( &bValue );
  354. if ( SUCCEEDED( hr ) ) {
  355. hr = BOOLToPropertyBag ( pIPropBag, L"FontItalic", bValue );
  356. }
  357. }
  358. }
  359. if ( SUCCEEDED( hr ) ) {
  360. if ( SUCCEEDED( hr ) ){
  361. hr = m_pIFont->get_Underline ( &bValue );
  362. if ( SUCCEEDED( hr ) ) {
  363. hr = BOOLToPropertyBag ( pIPropBag, L"FontUnderline", bValue );
  364. }
  365. }
  366. }
  367. if ( SUCCEEDED( hr ) ) {
  368. if ( SUCCEEDED( hr ) ){
  369. hr = m_pIFont->get_Strikethrough ( &bValue );
  370. if ( SUCCEEDED( hr ) ) {
  371. hr = BOOLToPropertyBag ( pIPropBag, L"FontStrikethrough", bValue );
  372. }
  373. }
  374. }
  375. if ( SUCCEEDED( hr ) ) {
  376. if ( SUCCEEDED( hr ) ){
  377. SHORT iValue;
  378. hr = m_pIFont->get_Weight ( &iValue );
  379. if ( SUCCEEDED( hr ) ) {
  380. hr = ShortToPropertyBag ( pIPropBag, L"FontWeight", iValue );
  381. }
  382. }
  383. }
  384. return hr;
  385. }
  386. //----------------------------------------------------------------------------
  387. // CImpIPropertyNotifySink Interface Implementation
  388. //----------------------------------------------------------------------------
  389. /*
  390. * CImpIPropertyNotifySink::CImpIPropertyNotifySink
  391. * CImpIPropertyNotifySink::~CImpIPropertyNotifySink
  392. *
  393. */
  394. CImpIPropertyNotifySink::CImpIPropertyNotifySink (
  395. IN COleFont *pOleFont
  396. )
  397. {
  398. m_cRef=0;
  399. m_pOleFont = pOleFont;
  400. }
  401. CImpIPropertyNotifySink::~CImpIPropertyNotifySink (
  402. void
  403. )
  404. {
  405. return;
  406. }
  407. /*
  408. * CImpIPropertyNotifySink::QueryInterface
  409. * CImpIPropertyNotifySink::AddRef
  410. * CImpIPropertyNotifySink::Release
  411. *
  412. * Purpose:
  413. * Non-delegating IUnknown members for CImpIPropertyNotifySink.
  414. */
  415. STDMETHODIMP
  416. CImpIPropertyNotifySink::QueryInterface (
  417. IN REFIID riid,
  418. OUT LPVOID *ppv
  419. )
  420. {
  421. *ppv=NULL;
  422. if (IID_IUnknown==riid || IID_IPropertyNotifySink==riid)
  423. *ppv=(LPVOID)this;
  424. if (NULL != *ppv) {
  425. ((LPUNKNOWN)*ppv)->AddRef();
  426. return NOERROR;
  427. }
  428. return ResultFromScode(E_NOINTERFACE);
  429. }
  430. STDMETHODIMP_(ULONG)
  431. CImpIPropertyNotifySink::AddRef(
  432. void
  433. )
  434. {
  435. return ++m_cRef;
  436. }
  437. STDMETHODIMP_(ULONG)
  438. CImpIPropertyNotifySink::Release (
  439. void
  440. )
  441. {
  442. if (0 != --m_cRef)
  443. return m_cRef;
  444. // delete this;
  445. return 0;
  446. }
  447. STDMETHODIMP
  448. CImpIPropertyNotifySink::OnChanged (
  449. IN DISPID DispId
  450. )
  451. {
  452. // Notify font object of change
  453. m_pOleFont->FontChange(DispId);
  454. return S_OK;
  455. }
  456. STDMETHODIMP
  457. CImpIPropertyNotifySink::OnRequestEdit (
  458. IN DISPID // DispId
  459. )
  460. {
  461. return S_OK;
  462. }