/*++ Copyright (C) 1996-1999 Microsoft Corporation Module Name: colefont.cpp Abstract: Font class. --*/ #include "polyline.h" #include "utils.h" #include "smonctrl.h" #include "unihelpr.h" #include "COleFont.h" #pragma warning ( disable : 4355 ) // "this" used in initializer list const LPWSTR COleFont::m_cwszDefaultFaceName = L"MS Shell Dlg"; const INT COleFont::m_iDefaultTmHeight = 13; const SHORT COleFont::m_iDefaultTmWeight = 400; const INT COleFont::m_iDefaultRiPxlsPerInch = 96; COleFont::COleFont ( CSysmonControl *pCtrl ) : m_NotifySink( this ) { m_pIFont = NULL; m_pIFontBold = NULL; m_pCtrl = pCtrl; m_pIConnPt = NULL; } #pragma warning ( default : 4355 ) // "this" used in initializer list COleFont::~COleFont ( void ) { // Release current connection point if (m_pIConnPt) { m_pIConnPt->Unadvise(m_dwCookie); ReleaseInterface(m_pIConnPt); } // Release fonts ReleaseInterface(m_pIFont); ReleaseInterface(m_pIFontBold); return; } void COleFont::InitDefaultFontDesc ( FONTDESC& rFontDesc, INT& riPxlsPerInch, WCHAR achFaceName[LF_FACESIZE+1]) { TEXTMETRIC TextMetrics; HFONT hFontOld; HDC hDC; USES_CONVERSION // Todo: Must define proper default values, move them to resources // for localization. ZeroMemory ( &rFontDesc, sizeof ( FONTDESC ) ); // Select default font hDC = GetDC(NULL); if ( NULL != hDC ) { hFontOld = SelectFont(hDC, (HFONT)GetStockObject(DEFAULT_GUI_FONT)); // Get face name and size GetTextMetrics(hDC, &TextMetrics); GetTextFaceW(hDC, LF_FACESIZE, achFaceName); // Get pixels per inch riPxlsPerInch = GetDeviceCaps(hDC, LOGPIXELSY); // Create a default font rFontDesc.lpstrName = achFaceName; rFontDesc.cySize.int64 = ((TextMetrics.tmHeight * 72) / riPxlsPerInch) * 10000; rFontDesc.sWeight = (short)TextMetrics.tmWeight; SelectFont(hDC, hFontOld); ReleaseDC(NULL, hDC); } else { riPxlsPerInch = m_iDefaultRiPxlsPerInch; lstrcpyW ( achFaceName, m_cwszDefaultFaceName ); // Create a default font rFontDesc.lpstrName = achFaceName; rFontDesc.cySize.int64 = ((m_iDefaultTmHeight * 72) / m_iDefaultRiPxlsPerInch) * 10000; rFontDesc.sWeight = m_iDefaultTmWeight; } rFontDesc.cbSizeofstruct = sizeof(rFontDesc); rFontDesc.sCharset = DEFAULT_CHARSET; rFontDesc.fItalic = 0; rFontDesc.fUnderline = 0; rFontDesc.fStrikethrough = 0; return; } HRESULT COleFont::Init ( VOID ) { HRESULT hr; FONTDESC fontDesc; WCHAR achFontFaceName[LF_FACESIZE+1]; LPFONT pIFont; INT iPxlsPerInch; InitDefaultFontDesc ( fontDesc, iPxlsPerInch, achFontFaceName ); hr = OleCreateFontIndirect(&fontDesc, IID_IFont, (void**)&pIFont); if (FAILED(hr)) return hr; pIFont->SetRatio(iPxlsPerInch, HIMETRIC_PER_INCH); hr = SetIFont(pIFont); pIFont->Release(); return hr; } STDMETHODIMP COleFont::SetIFont( LPFONT pIFont ) { HRESULT hr; IConnectionPointContainer *pIConnPtCont; IPropertyNotifySink *pISink; // Release current connection point if (m_pIConnPt) { m_pIConnPt->Unadvise(m_dwCookie); ReleaseInterface(m_pIConnPt); } // Release current fonts ReleaseInterface(m_pIFont); ReleaseInterface(m_pIFontBold); // Addref and hold new IFont m_pIFont = pIFont; m_pIFont->AddRef(); // Get it's property notify connection point hr = pIFont->QueryInterface(IID_IConnectionPointContainer, (void **)&pIConnPtCont); if (SUCCEEDED(hr)) { hr = pIConnPtCont->FindConnectionPoint(IID_IPropertyNotifySink, &m_pIConnPt); pIConnPtCont->Release(); // Connect our sink to it if (SUCCEEDED(hr)) { m_NotifySink.QueryInterface(IID_IPropertyNotifySink, (void **)&pISink); hr = m_pIConnPt->Advise(pISink, &m_dwCookie); } } // Force a change notification FontChange(DISPID_UNKNOWN); return hr; } void COleFont::FontChange ( DISPID DispId ) { CY size; BOOL bool; short weight; BSTR bstrName; // if not bold font, force clone of normal font if (m_pIFontBold == NULL) DispId = DISPID_UNKNOWN; // Copy changed parameter to bold font switch (DispId) { case DISPID_FONT_NAME: if (SUCCEEDED(m_pIFont->get_Name(&bstrName))) { m_pIFontBold->put_Name(bstrName); SysFreeString(bstrName); } break; case DISPID_FONT_SIZE: m_pIFont->get_Size(&size); m_pIFontBold->put_Size(size); break; case DISPID_FONT_ITALIC: m_pIFont->get_Italic(&bool); m_pIFontBold->put_Italic(bool); break; case DISPID_FONT_UNDER: m_pIFont->get_Underline(&bool); m_pIFontBold->put_Underline(bool); break; case DISPID_FONT_STRIKE: m_pIFont->get_Strikethrough(&bool); m_pIFontBold->put_Strikethrough(bool); break; case DISPID_FONT_WEIGHT: m_pIFont->get_Weight(&weight); m_pIFontBold->put_Weight(weight); m_pIFontBold->put_Bold(TRUE); break; case DISPID_UNKNOWN: ReleaseInterface(m_pIFontBold); if (SUCCEEDED(m_pIFont->Clone(&m_pIFontBold))) { m_pIFontBold->put_Bold(TRUE); } } // Notify owner of font change m_pCtrl->FontChanged(); } STDMETHODIMP COleFont::GetFontDisp ( OUT IFontDisp **ppFont ) { *ppFont = NULL; if (m_pIFont == NULL) return E_UNEXPECTED; return m_pIFont->QueryInterface(IID_IFontDisp, (void **)ppFont); } STDMETHODIMP COleFont::GetHFont ( OUT HFONT *phFont ) { if ( m_pIFont == NULL ) { *phFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); } else { if ( FAILED(m_pIFont->get_hFont(phFont)) ) { *phFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); } } return S_OK; } STDMETHODIMP COleFont::GetHFontBold ( OUT HFONT *phFont ) { if (m_pIFontBold == NULL ) { *phFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); } else { if ( FAILED(m_pIFontBold->get_hFont(phFont)) ) { *phFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); } } return S_OK; } STDMETHODIMP COleFont::LoadFromStream ( LPSTREAM pIStream ) { HRESULT hr; IPersistStream *pIPersist = NULL; FONTDESC fontDesc; WCHAR achFontFaceName[LF_FACESIZE+1]; LPFONT pIFont = NULL; INT iPxlsPerInch; if (m_pIFont == NULL) return E_FAIL; // Calling pIPersist for the existing font seems to miss some // important notification, so create a new font, load properties // from the stream, and replace the current font. InitDefaultFontDesc ( fontDesc, iPxlsPerInch, achFontFaceName ); hr = OleCreateFontIndirect(&fontDesc, IID_IFont, (void**)&pIFont); if (FAILED(hr)) return hr; pIFont->SetRatio(iPxlsPerInch, HIMETRIC_PER_INCH); hr = pIFont->QueryInterface(IID_IPersistStream, (void **)&pIPersist); if (SUCCEEDED(hr)) { hr = pIPersist->Load(pIStream); pIPersist->Release(); hr = SetIFont(pIFont); } pIFont->Release(); return hr; } STDMETHODIMP COleFont::SaveToStream ( LPSTREAM pIStream, BOOL fClearDirty ) { IPersistStream *pIPersist; HRESULT hr; if (m_pIFont == NULL) return E_FAIL; hr = m_pIFont->QueryInterface(IID_IPersistStream, (void **)&pIPersist); if (SUCCEEDED(hr)) { hr = pIPersist->Save(pIStream, fClearDirty); pIPersist->Release(); } return hr; } HRESULT COleFont::LoadFromPropertyBag ( IPropertyBag* pIPropBag, IErrorLog* pIErrorLog ) { HRESULT hr = S_OK; WCHAR achFontFaceName[LF_FACESIZE+1]; WCHAR achPropBagFaceName[LF_FACESIZE+1]; INT iBufSize = LF_FACESIZE+1; FONTDESC fontDesc; LPFONT pIFont; VARIANT vValue; BOOL bValue; SHORT iValue; CY cySize; INT iPxlsPerInch; if (m_pIFont == NULL) return E_FAIL; InitDefaultFontDesc ( fontDesc, iPxlsPerInch, achFontFaceName ); hr = StringFromPropertyBag ( pIPropBag, pIErrorLog, L"FontName", achPropBagFaceName, iBufSize ); if ( SUCCEEDED( hr ) ) { fontDesc.lpstrName = T2W(achPropBagFaceName); } hr = CyFromPropertyBag ( pIPropBag, pIErrorLog, L"FontSize", cySize ); if ( SUCCEEDED( hr ) ){ fontDesc.cySize.int64 = cySize.int64; } hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, L"FontItalic", bValue ); if ( SUCCEEDED( hr ) ){ fontDesc.fItalic = ( 0 == bValue ? 0 : 1 ); } hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, L"FontUnderline", bValue ); if ( SUCCEEDED( hr ) ){ fontDesc.fUnderline = ( 0 == bValue ? 0 : 1 ); } hr = BOOLFromPropertyBag ( pIPropBag, pIErrorLog, L"FontStrikethrough", bValue ); if ( SUCCEEDED( hr ) ){ fontDesc.fStrikethrough = ( 0 == bValue ? 0 : 1 ); } hr = ShortFromPropertyBag ( pIPropBag, pIErrorLog, L"FontWeight", iValue ); if ( SUCCEEDED( hr ) ){ fontDesc.sWeight = iValue; } hr = OleCreateFontIndirect(&fontDesc, IID_IFont, (void**)&pIFont); if (FAILED(hr)) return hr; // pIFont->SetRatio(iPxlsPerInch, HIMETRIC_PER_INCH); hr = SetIFont(pIFont); pIFont->Release(); VariantClear ( &vValue ); return hr; } HRESULT COleFont::SaveToPropertyBag ( IPropertyBag* pIPropBag, BOOL /* fClearDirty */, BOOL /* fSaveAllProps */ ) { HRESULT hr = NOERROR; VARIANT vValue; BOOL bValue; if (m_pIFont == NULL) return E_FAIL; VariantInit( &vValue ); vValue.vt = VT_BSTR; hr = m_pIFont->get_Name( &vValue.bstrVal); if ( SUCCEEDED( hr ) ) { hr = pIPropBag->Write(L"FontName", &vValue ); VariantClear ( &vValue ); } if ( SUCCEEDED( hr ) ) { if ( SUCCEEDED( hr ) ){ CY cySize; hr = m_pIFont->get_Size ( &cySize ); if ( SUCCEEDED( hr ) ) { hr = CyToPropertyBag ( pIPropBag, L"FontSize", cySize ); } } } if ( SUCCEEDED( hr ) ) { if ( SUCCEEDED( hr ) ){ hr = m_pIFont->get_Italic ( &bValue ); if ( SUCCEEDED( hr ) ) { hr = BOOLToPropertyBag ( pIPropBag, L"FontItalic", bValue ); } } } if ( SUCCEEDED( hr ) ) { if ( SUCCEEDED( hr ) ){ hr = m_pIFont->get_Underline ( &bValue ); if ( SUCCEEDED( hr ) ) { hr = BOOLToPropertyBag ( pIPropBag, L"FontUnderline", bValue ); } } } if ( SUCCEEDED( hr ) ) { if ( SUCCEEDED( hr ) ){ hr = m_pIFont->get_Strikethrough ( &bValue ); if ( SUCCEEDED( hr ) ) { hr = BOOLToPropertyBag ( pIPropBag, L"FontStrikethrough", bValue ); } } } if ( SUCCEEDED( hr ) ) { if ( SUCCEEDED( hr ) ){ SHORT iValue; hr = m_pIFont->get_Weight ( &iValue ); if ( SUCCEEDED( hr ) ) { hr = ShortToPropertyBag ( pIPropBag, L"FontWeight", iValue ); } } } return hr; } //---------------------------------------------------------------------------- // CImpIPropertyNotifySink Interface Implementation //---------------------------------------------------------------------------- /* * CImpIPropertyNotifySink::CImpIPropertyNotifySink * CImpIPropertyNotifySink::~CImpIPropertyNotifySink * */ CImpIPropertyNotifySink::CImpIPropertyNotifySink ( IN COleFont *pOleFont ) { m_cRef=0; m_pOleFont = pOleFont; } CImpIPropertyNotifySink::~CImpIPropertyNotifySink ( void ) { return; } /* * CImpIPropertyNotifySink::QueryInterface * CImpIPropertyNotifySink::AddRef * CImpIPropertyNotifySink::Release * * Purpose: * Non-delegating IUnknown members for CImpIPropertyNotifySink. */ STDMETHODIMP CImpIPropertyNotifySink::QueryInterface ( IN REFIID riid, OUT LPVOID *ppv ) { *ppv=NULL; if (IID_IUnknown==riid || IID_IPropertyNotifySink==riid) *ppv=(LPVOID)this; if (NULL != *ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; } return ResultFromScode(E_NOINTERFACE); } STDMETHODIMP_(ULONG) CImpIPropertyNotifySink::AddRef( void ) { return ++m_cRef; } STDMETHODIMP_(ULONG) CImpIPropertyNotifySink::Release ( void ) { if (0 != --m_cRef) return m_cRef; // delete this; return 0; } STDMETHODIMP CImpIPropertyNotifySink::OnChanged ( IN DISPID DispId ) { // Notify font object of change m_pOleFont->FontChange(DispId); return S_OK; } STDMETHODIMP CImpIPropertyNotifySink::OnRequestEdit ( IN DISPID // DispId ) { return S_OK; }