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
649 lines
14 KiB
/*++
|
|
|
|
Copyright (C) 1996-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
colefont.cpp
|
|
|
|
Abstract:
|
|
|
|
Font class.
|
|
|
|
--*/
|
|
|
|
#include "polyline.h"
|
|
#include <strsafe.h>
|
|
#include "unihelpr.h"
|
|
#include "winhelpr.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;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
void
|
|
COleFont::InitDefaultFontDesc (
|
|
FONTDESC& rFontDesc,
|
|
INT& riPxlsPerInch,
|
|
WCHAR achFaceName[LF_FACESIZE+1]
|
|
)
|
|
{
|
|
TEXTMETRIC TextMetrics;
|
|
HFONT hFontOld;
|
|
HDC hDC;
|
|
|
|
// 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
|
|
//
|
|
// TODO: Should we check the return error code here?
|
|
//
|
|
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;
|
|
StringCchCopy(achFaceName, LF_FACESIZE+1, 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;
|
|
}
|
|
|
|
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
|
|
ClearInterface(m_pIFont);
|
|
ClearInterface(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 boolVal;
|
|
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(&boolVal);
|
|
m_pIFontBold->put_Italic(boolVal);
|
|
break;
|
|
|
|
case DISPID_FONT_UNDER:
|
|
m_pIFont->get_Underline(&boolVal);
|
|
m_pIFontBold->put_Underline(boolVal);
|
|
break;
|
|
|
|
case DISPID_FONT_STRIKE:
|
|
m_pIFont->get_Strikethrough(&boolVal);
|
|
m_pIFontBold->put_Strikethrough(boolVal);
|
|
break;
|
|
|
|
case DISPID_FONT_WEIGHT:
|
|
m_pIFont->get_Weight(&weight);
|
|
m_pIFontBold->put_Weight(weight);
|
|
m_pIFontBold->put_Bold(TRUE);
|
|
break;
|
|
|
|
case DISPID_UNKNOWN:
|
|
ClearInterface(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
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (ppFont == NULL) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
try {
|
|
*ppFont = NULL;
|
|
|
|
if (m_pIFont == NULL) {
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
else {
|
|
hr = m_pIFont->QueryInterface(IID_IFontDisp, (void **)ppFont);
|
|
}
|
|
} catch (...) {
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP COleFont::GetHFont (
|
|
OUT HFONT *phFont
|
|
)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (phFont == NULL) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
try {
|
|
*phFont = NULL;
|
|
|
|
if (m_pIFont != NULL ) {
|
|
hr = m_pIFont->get_hFont(phFont);
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
*phFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
|
|
}
|
|
} catch (...) {
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP COleFont::GetHFontBold (
|
|
OUT HFONT *phFont
|
|
)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (phFont == NULL) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
try {
|
|
*phFont = NULL;
|
|
|
|
if (m_pIFontBold != NULL ) {
|
|
hr = m_pIFontBold->get_hFont(phFont);
|
|
}
|
|
|
|
if ( FAILED(hr)) {
|
|
*phFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
|
|
}
|
|
} catch (...) {
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP COleFont::LoadFromStream (
|
|
IN 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_UNEXPECTED;
|
|
}
|
|
|
|
// 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 (
|
|
IN LPSTREAM pIStream,
|
|
IN BOOL fClearDirty
|
|
)
|
|
{
|
|
IPersistStream *pIPersist = NULL;
|
|
HRESULT hr;
|
|
|
|
if (m_pIFont == NULL) {
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
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_UNEXPECTED;
|
|
}
|
|
|
|
InitDefaultFontDesc ( fontDesc, iPxlsPerInch, achFontFaceName );
|
|
|
|
hr = StringFromPropertyBag (
|
|
pIPropBag,
|
|
pIErrorLog,
|
|
L"FontName",
|
|
achPropBagFaceName,
|
|
iBufSize );
|
|
|
|
if ( SUCCEEDED( hr ) ) {
|
|
fontDesc.lpstrName = 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;
|
|
CY cySize;
|
|
SHORT iValue;
|
|
|
|
if (m_pIFont == NULL) {
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
do {
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_BSTR;
|
|
hr = m_pIFont->get_Name( &vValue.bstrVal);
|
|
|
|
if (!SUCCEEDED(hr)) {
|
|
break;
|
|
}
|
|
hr = pIPropBag->Write(L"FontName", &vValue );
|
|
VariantClear ( &vValue );
|
|
if (!SUCCEEDED(hr)) {
|
|
break;
|
|
}
|
|
|
|
hr = m_pIFont->get_Size ( &cySize );
|
|
if (!SUCCEEDED(hr)) {
|
|
break;
|
|
}
|
|
hr = CyToPropertyBag ( pIPropBag, L"FontSize", cySize );
|
|
if (!SUCCEEDED(hr)) {
|
|
break;
|
|
}
|
|
|
|
hr = m_pIFont->get_Italic ( &bValue );
|
|
if (!SUCCEEDED(hr)) {
|
|
break;
|
|
}
|
|
hr = BOOLToPropertyBag ( pIPropBag, L"FontItalic", bValue );
|
|
if (!SUCCEEDED(hr)) {
|
|
break;
|
|
}
|
|
|
|
hr = m_pIFont->get_Underline ( &bValue );
|
|
if (!SUCCEEDED(hr)) {
|
|
break;
|
|
}
|
|
hr = BOOLToPropertyBag ( pIPropBag, L"FontUnderline", bValue );
|
|
if (!SUCCEEDED(hr)) {
|
|
break;
|
|
}
|
|
|
|
hr = m_pIFont->get_Strikethrough ( &bValue );
|
|
if (!SUCCEEDED(hr)) {
|
|
break;
|
|
}
|
|
hr = BOOLToPropertyBag ( pIPropBag, L"FontStrikethrough", bValue );
|
|
if (!SUCCEEDED(hr)) {
|
|
break;
|
|
}
|
|
|
|
hr = m_pIFont->get_Weight ( &iValue );
|
|
if (!SUCCEEDED(hr)) {
|
|
break;
|
|
}
|
|
hr = ShortToPropertyBag ( pIPropBag, L"FontWeight", iValue );
|
|
} while (0);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// CImpIPropertyNotifySink Interface Implementation
|
|
//----------------------------------------------------------------------------
|
|
|
|
/*
|
|
* CImpIPropertyNotifySink::CImpIPropertyNotifySink
|
|
* CImpIPropertyNotifySink::~CImpIPropertyNotifySink
|
|
*
|
|
*/
|
|
|
|
CImpIPropertyNotifySink::CImpIPropertyNotifySink (
|
|
IN COleFont *pOleFont
|
|
)
|
|
{
|
|
m_cRef=0;
|
|
m_pOleFont = pOleFont;
|
|
}
|
|
|
|
|
|
CImpIPropertyNotifySink::~CImpIPropertyNotifySink (
|
|
void
|
|
)
|
|
{
|
|
}
|
|
|
|
|
|
/*
|
|
* CImpIPropertyNotifySink::QueryInterface
|
|
* CImpIPropertyNotifySink::AddRef
|
|
* CImpIPropertyNotifySink::Release
|
|
*
|
|
* Purpose:
|
|
* Non-delegating IUnknown members for CImpIPropertyNotifySink.
|
|
*/
|
|
|
|
STDMETHODIMP
|
|
CImpIPropertyNotifySink::QueryInterface (
|
|
IN REFIID riid,
|
|
OUT LPVOID *ppv
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (ppv == NULL) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
try {
|
|
*ppv=NULL;
|
|
|
|
if (IID_IUnknown==riid || IID_IPropertyNotifySink==riid) {
|
|
*ppv = (LPVOID)this;
|
|
AddRef();
|
|
}
|
|
else {
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
} catch (...) {
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
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;
|
|
}
|