Leaked source code of windows server 2003
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.

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