/////////////////////////////////////////////////////////////////////////////////////////
// Project: SP Numeric Edit Control 1.0
//
// File: NumericEditBox.cpp
//
// Developer(s): Sergei Pavlovsky
// sergei_vp@hotmail.com
// Copyright (c) 2004
//
// Description: Implementation of CoNumericEditBox class.
// CoNumericEditBox represents ActiveX control.
//
// Platforms: Win32
//
// This code may be used in compiled form in any way you desire. This file may be
// redistributed unmodified by any means PROVIDING it is not sold for profit without
// the authors written consent, and providing that this notice and the authors name
// is included. If the source code in this file is used in any commercial application
// then acknowledgement must be made to the author of this file (in whatever form
// you wish).
//
// This file is provided "as is" with no expressed or implied warranty. The author
// accepts no liability for any damage/loss of business that this product may cause.
/////////////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "NumericEditBox.h"
#include "SpNumericEditModule.h"
#include <map>
/////////////////////////////////////////////////////////////////////////////////////////
// CoNumericEditBox::CFontPropertyNotifySink class implementation
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
// IPropertyNotifySink implementation
STDMETHODIMP CoNumericEditBox::CFontPropertyNotifySink::OnRequestEdit(DISPID dispid)
{
if ( m_pOwner )
{
if ( m_pOwner->m_nFreezeEvents )
return S_FALSE;
return m_pOwner->FireOnRequestEdit(DISPID_FONT);
}
return S_OK;
}
STDMETHODIMP CoNumericEditBox::CFontPropertyNotifySink::OnChanged(DISPID dispid)
{
if ( m_pOwner )
{
m_pOwner->m_ctlEdit._OnFontChanging();
m_pOwner->m_bRequiresSave = TRUE;
if ( m_pOwner->m_nFreezeEvents == 0 )
m_pOwner->FireOnChanged(DISPID_FONT);
m_pOwner->m_ctlEdit._OnFontChanged();
m_pOwner->FireViewChange();
m_pOwner->SendOnDataChange(NULL);
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////////////////
// CoNumericEditBox class implementation
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
// Constants
LPCOLESTR CoNumericEditBox::ms_rgszParamNames[] =
{
L"ValueType",
L"FormatType",
L"DisplayMask",
L"EditingMask"
};
SIZE_T CoNumericEditBox::ms_cchMaxParamName = 11;
/////////////////////////////////////////////////////////////////////////////////////////
// Construction & destruction
#pragma warning(push)
#pragma warning(disable: 4355) // 'this' : used in base member initializer list
CoNumericEditBox::CoNumericEditBox()
: m_ctlEdit(_T("Edit"), this, 1),
m_pcoFontNS(NULL),
m_pcoFormatter(NULL)
{
m_bWindowOnly = TRUE;
}
#pragma warning(pop)
CoNumericEditBox::~CoNumericEditBox()
{
ATLASSERT( m_pcoFontNS == NULL );
ATLASSERT( m_pcoFormatter == NULL );
}
HRESULT CoNumericEditBox::FinalConstruct()
{
ATLASSERT( !m_pcoFontNS );
// Set internal event sink to edit window.
m_ctlEdit.AdviseEventSink(this);
// Create Property Notify sink
HRESULT hr = CComObject<CFontPropertyNotifySink>::CreateInstance(&m_pcoFontNS);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
return hr;
m_pcoFontNS->AddRef();
m_pcoFontNS->Initialize(this);
return S_OK;
}
void CoNumericEditBox::FinalRelease()
{
ATLASSERT( m_pcoFontNS );
// Free Property Notify sink
if ( m_pcoFontNS->GetCookie() )
m_pcoFontNS->Unadvise(m_ctlEdit._GetRefFont());
m_pcoFontNS->Uninitialize();
m_pcoFontNS->Release();
m_pcoFontNS = NULL;
// Discard internal event sink of edit window.
m_ctlEdit.UnadviseEventSink();
}
/////////////////////////////////////////////////////////////////////////////////////////
// Helpers: Parsing of Params string
bool CoNumericEditBox::ReadParamID(LPCOLESTR lpParams, UINT cchParams, UINT unPos,
UINT* punNext, ParamsEnum* penID)
{
ATLASSERT( !::IsBadReadPtr(lpParams, cchParams * sizeof(OLECHAR)) );
ATLASSERT( unPos < cchParams);
ATLASSERT( !::IsBadReadPtr(punNext, sizeof(UINT)) );
ATLASSERT( !::IsBadReadPtr(penID, sizeof(ParamsEnum)) );
*penID = TN_NON;
olestring sParamName;
sParamName.reserve(ms_cchMaxParamName);
*punNext = unPos;
for ( UINT i = unPos; i < cchParams; i++ )
{
OLECHAR chCurrent = lpParams[i];
if ( chCurrent == L' ' ||
chCurrent == L'\x9' ||
chCurrent == L'=' )
break;
sParamName.push_back(chCurrent);
}
*punNext = i;
for ( UINT i = 0; i < sizeof(ms_rgszParamNames)/sizeof(LPCOLESTR); i++ )
{
LPCOLESTR lpcszCurrentParamName = ms_rgszParamNames[i];
if ( sParamName == lpcszCurrentParamName )
{
*penID = static_cast<ParamsEnum>(i + 1);
break;
}
}
if ( !(*penID) )
{
UINT_PTR cBuf;
// Load Error Source
cBuf = _AtlModule.LoadString(IDS_ELS_SPNUMERICEDITBOX, NULL, 0);
LPTSTR lpszSrc = LPTSTR(_alloca((cBuf + 1) * sizeof(TCHAR)));
_AtlModule.LoadString(IDS_ELS_SPNUMERICEDITBOX, lpszSrc, cBuf + 1);
lpszSrc[cBuf] = _T('\x0');
// Load Error Reason format
cBuf = _AtlModule.LoadString(IDS_ERCC_UNRECOGNIZEDPARAM, NULL, 0);
LPTSTR lpszFmt = LPTSTR(_alloca((cBuf + 1) * sizeof(TCHAR)));
_AtlModule.LoadString(IDS_ERCC_UNRECOGNIZEDPARAM, lpszFmt, cBuf + 1);
lpszFmt[cBuf] = _T('\x0');
// Format Error Message
cBuf += sParamName.length();
LPTSTR lpszMsg = LPTSTR(_alloca((cBuf + 1) * sizeof(TCHAR)));
_stprintf(lpszMsg, lpszFmt, sParamName.c_str());
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, lpszSrc, 0, lpszMsg);
return false;
}
return true;
}
void CoNumericEditBox::WriteParamID(ParamsEnum enID, olestring& sParams)
{
ATLASSERT( enID <= sizeof(ms_rgszParamNames)/sizeof(LPCOLESTR) );
sParams.append(ms_rgszParamNames[enID - 1]);
}
bool CoNumericEditBox::ReadParamValue(LPCOLESTR lpParams, UINT cchParams, UINT unPos,
UINT* punNext, BSTR* pbsValue)
{
ATLASSERT( !::IsBadReadPtr(lpParams, cchParams * sizeof(OLECHAR)) );
ATLASSERT( unPos < cchParams);
ATLASSERT( !::IsBadReadPtr(punNext, sizeof(UINT)) );
ATLASSERT( !::IsBadReadPtr(pbsValue, sizeof(BSTR)) );
olestring sValue;
sValue.reserve(cchParams - unPos);
*punNext = unPos;
if ( unPos < cchParams && lpParams[unPos] == L'"' )
{
// Value is surrounded with double quotes.
for ( UINT i = unPos + 1; i < cchParams; i++ )
{
OLECHAR chCurrent = lpParams[i];
if ( chCurrent == L'"' )
{
if ( i + 1 < cchParams && lpParams[i + 1] == L'"' )
i++;
else
break;
}
sValue.push_back(chCurrent);
}
if ( lpParams[i] != L'"' || i == unPos )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_NOCLOSINGQUOTE);
return false;
}
*punNext = i + 1;
*pbsValue = ::SysAllocStringLen(sValue.c_str(), UINT(sValue.length()));
}
else
{
// Value is not surrounded with double quotes.
for ( UINT i = unPos; i < cchParams; i++ )
{
OLECHAR chCurrent = lpParams[i];
if ( chCurrent == L';' )
break;
if ( chCurrent == L'"' )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX,
0, IDS_ERCC_PARAMVALUEQUOTES);
return false;
}
sValue.push_back(chCurrent);
}
*punNext = i;
if ( !sValue.empty() )
{
*pbsValue = ::SysAllocStringLen(sValue.c_str(), UINT(sValue.length()));
ATLASSERT( *pbsValue );
if ( !(*pbsValue) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 2,
IDS_ELR_OUTOFMEMORY);
return false;
}
}
else
{
*pbsValue = NULL;
}
}
return true;
}
void CoNumericEditBox::WriteParamValue(LPCOLESTR lpValue, UINT cchValue,
olestring& sParams, bool bInsideQuotes)
{
ATLASSERT( !::IsBadReadPtr(lpValue, cchValue * sizeof(WCHAR)) );
if ( bInsideQuotes )
{
sParams.push_back(L'\"');
sParams.reserve(sParams.size() + cchValue);
for ( UINT i = 0; i < cchValue; i++ )
{
OLECHAR chCurrent = lpValue[i];
if ( chCurrent == L'\"' )
sParams.push_back(L'\"');
sParams.push_back(chCurrent);
}
sParams.push_back(L'\"');
}
else
{
sParams.append(lpValue, lpValue + cchValue);
}
}
/////////////////////////////////////////////////////////////////////////////////////////
// Operations: Parsing of Params string
HRESULT CoNumericEditBox::ParseFormatterParamString(BSTR bsParams,
ValueTypeConstants* penValueType,
FormatTypeConstants* penFormatType,
BSTR* pbsDisplayMask,
BSTR* pbsEditingMask)
{
ATLASSERT( !::IsBadWritePtr(penValueType, sizeof(ValueTypeConstants)) );
ATLASSERT( !::IsBadWritePtr(penFormatType, sizeof(FormatTypeConstants)) );
ATLASSERT( !::IsBadWritePtr(pbsDisplayMask, sizeof(BSTR)) );
ATLASSERT( !::IsBadWritePtr(pbsEditingMask, sizeof(BSTR)) );
enum ParseStatusEnum
{
PS_EXPECTPARAMNAME = 0,
PS_EXPECTASSIGNMENT = 1,
PS_EXPECTPARAMVALUE = 2,
PS_EXPECTPARAMEND = 3
};
typedef std::map<ParamsEnum, CComBSTR> CParamValuesMap;
*penValueType = ValueTypeConstants(0);
*penFormatType = FormatTypeConstants(0);
*pbsDisplayMask = NULL;
*pbsEditingMask = NULL;
if ( bsParams )
{
CParamValuesMap mapParams;
std::pair<CParamValuesMap::iterator, bool> pairInsRes;
ParamsEnum enCurrentParam = TN_NON;
CComBSTR cbsCurrentValue;
ParseStatusEnum enParseStatus = PS_EXPECTPARAMNAME;
UINT cchParams = ::SysStringLen(bsParams);
for ( UINT i = 0; i < cchParams; )
{
switch ( bsParams[i] )
{
case _T(' '):
case _T('\x9'):
i++; // Skip white spaces
break;
case _T('='):
if ( enParseStatus != PS_EXPECTASSIGNMENT )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX,
0, IDS_ERCC_UNEXPECTEDASSIGNMENTSIGN);
return E_FAIL;
}
i++;
enParseStatus = PS_EXPECTPARAMVALUE;
break;
case _T(';'):
if ( enParseStatus != PS_EXPECTPARAMEND &&
enParseStatus != PS_EXPECTPARAMVALUE )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX,
0, IDS_ERCC_UNEXPECTEDSEMICOLONSIGN);
return E_FAIL;
}
pairInsRes = mapParams.insert(CParamValuesMap::value_type(enCurrentParam,
cbsCurrentValue));
if ( !pairInsRes.second )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX,
0, IDS_ERCC_DUAPLICATEDPARAM);
return E_FAIL;
}
enCurrentParam = TN_NON;
cbsCurrentValue = BSTR(NULL);
i++;
enParseStatus = PS_EXPECTPARAMNAME;
break;
default:
if ( enParseStatus == PS_EXPECTPARAMNAME )
{
// Define Param
UINT iNext;
bool bResult = ReadParamID(bsParams, cchParams, i,
&iNext, &enCurrentParam);
ATLASSERT( bResult );
if ( !bResult )
{
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX,
0, IDS_ERCC_READPARAMNAME);
return E_FAIL;
}
enParseStatus = PS_EXPECTASSIGNMENT;
i = iNext;
}
else
{
ATLASSERT( enParseStatus == PS_EXPECTPARAMVALUE );
UINT iNext;
bool bResult = ReadParamValue(bsParams, cchParams, i,
&iNext, &cbsCurrentValue);
ATLASSERT( bResult );
if ( !bResult )
{
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX,
0, IDS_ERCC_READPARAMVALUE);
return E_FAIL;
}
enParseStatus = PS_EXPECTPARAMEND;
i = iNext;
}
break;
}
}
// Add last parameter
if ( enCurrentParam != TN_NON )
{
pairInsRes = mapParams.insert(CParamValuesMap::value_type(enCurrentParam,
cbsCurrentValue));
if ( !pairInsRes.second )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX,
0, IDS_ERCC_DUAPLICATEDPARAM);
return E_FAIL;
}
}
// Convert parameter values
CComPtr<ITypeLib> spiTLB;
BOOL bResult = CSpNumericEditModule::LoadTypeLib(&spiTLB);
ATLASSERT( bResult );
if ( !bResult )
{
SP::AccountError(SP::AE_LOG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_GETTYPELIBRARY);
return E_FAIL;
}
for ( CParamValuesMap::iterator it = mapParams.begin();
it != mapParams.end(); it++ )
{
CComBSTR& cbsValue = (*it).second;
switch ( (*it).first )
{
case TN_VALUETYPE:
{
CComPtr<ITypeInfo> spiTI;
bResult = CSpNumericEditModule::GetValueTypesTypeInfo(spiTLB, &spiTI);
ATLASSERT( bResult );
if ( !bResult )
{
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_GETVALUETYPEINFORMATION);
return E_FAIL;
}
LONG lValue;
bResult = CSpNumericEditModule::ConvertEnumValueName(spiTI, cbsValue,
&lValue);
ATLASSERT( bResult );
if ( !bResult )
{
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_GETVALUETYPECONSTNAME);
return E_FAIL;
}
*penValueType = ValueTypeConstants(lValue);
}
break;
case TN_FORMATTYPE:
{
CComPtr<ITypeInfo> spiTI;
bResult = CSpNumericEditModule::GetFormatTypesTypeInfo(spiTLB, &spiTI);
ATLASSERT( bResult );
if ( !bResult )
{
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_GETFORMATTYPEINFORMATION);
return E_FAIL;
}
LONG lValue;
bResult = CSpNumericEditModule::ConvertEnumValueName(spiTI, cbsValue,
&lValue);
ATLASSERT( bResult );
if ( !bResult )
{
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_GETFORMATTYPECONSTNAME);
return E_FAIL;
}
*penFormatType = FormatTypeConstants(lValue);
}
break;
case TN_DISPLAYMASK:
*pbsDisplayMask = cbsValue.Detach();
break;
case TN_EDITINGMASK:
*pbsEditingMask = cbsValue.Detach();
break;
}
}
}
return S_OK;
}
HRESULT CoNumericEditBox::BuildFormatterParamString(ValueTypeConstants enValueType,
FormatTypeConstants enFormatType,
LPCOLESTR lpszDisplayMask,
LPCOLESTR lpszEditingMask,
BSTR* pbsParams)
{
ATLASSERT( !::IsBadWritePtr(pbsParams, sizeof(BSTR)) );
*pbsParams = NULL;
olestring sBuffer;
sBuffer.reserve(128);
CComPtr<ITypeLib> spiTLB;
BOOL bResult = CSpNumericEditModule::LoadTypeLib(&spiTLB);
ATLASSERT( bResult );
if ( !bResult )
{
SP::AccountError(SP::AE_LOG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_GETTYPELIBRARY);
return E_FAIL;
}
// Add ValueType parameter
if ( enValueType )
{
CComPtr<ITypeInfo> spiTI;
bResult = CSpNumericEditModule::GetValueTypesTypeInfo(spiTLB, &spiTI);
ATLASSERT( bResult );
if ( !bResult )
{
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_GETVALUETYPEINFORMATION);
return E_FAIL;
}
CComBSTR cbsValue;
bResult = CSpNumericEditModule::ConvertEnumValueName(spiTI, enValueType, &cbsValue);
ATLASSERT( bResult );
if ( !bResult )
{
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_GETVALUETYPECONSTNAME);
return E_FAIL;
}
WriteParamID(TN_VALUETYPE, sBuffer);
sBuffer.push_back(L'=');
WriteParamValue(cbsValue, cbsValue.Length(), sBuffer, false);
sBuffer.push_back(L';');
}
// Add FormatType parameter
if ( enFormatType )
{
if ( !sBuffer.empty() )
sBuffer.push_back(L' ');
CComPtr<ITypeInfo> spiTI;
bResult = CSpNumericEditModule::GetFormatTypesTypeInfo(spiTLB, &spiTI);
ATLASSERT( bResult );
if ( !bResult )
{
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_GETFORMATTYPEINFORMATION);
return E_FAIL;
}
CComBSTR cbsValue;
bResult = CSpNumericEditModule::ConvertEnumValueName(spiTI, enFormatType, &cbsValue);
ATLASSERT( bResult );
if ( !bResult )
{
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_GETFORMATTYPECONSTNAME);
return E_FAIL;
}
WriteParamID(TN_FORMATTYPE, sBuffer);
sBuffer.push_back(L'=');
WriteParamValue(cbsValue, cbsValue.Length(), sBuffer, false);
sBuffer.push_back(L';');
}
// Add DisplayMask parameter
if ( lpszDisplayMask )
{
if ( !sBuffer.empty() )
sBuffer.push_back(L' ');
WriteParamID(TN_DISPLAYMASK, sBuffer);
sBuffer.push_back(L'=');
WriteParamValue(lpszDisplayMask, UINT(wcslen(lpszDisplayMask)), sBuffer, true);
sBuffer.push_back(L';');
}
// Add EditingMask parameter
if ( lpszEditingMask )
{
if ( !sBuffer.empty() )
sBuffer.push_back(L' ');
WriteParamID(TN_EDITINGMASK, sBuffer);
sBuffer.push_back(L'=');
WriteParamValue(lpszEditingMask, UINT(wcslen(lpszEditingMask)), sBuffer, true);
sBuffer.push_back(L';');
}
// Allocate system string
if ( !sBuffer.empty() )
{
*pbsParams = ::SysAllocStringLen(sBuffer.c_str(), UINT(sBuffer.length()));
ATLASSERT( *pbsParams );
if ( !(*pbsParams) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 2,
IDS_ELR_OUTOFMEMORY);
return E_OUTOFMEMORY;
}
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Operations: Formatter
HRESULT CoNumericEditBox::GetFormatter(IFormatter** ppiFormatter)
{
ATLASSERT( !::IsBadWritePtr(ppiFormatter, sizeof(IFormatter*)) );
// Code below is not comletely safe to be used with multithreading.
Lock();
__try
{
if ( !m_pcoFormatter )
{
HRESULT hr = CComObject<CoFormatter>::CreateInstance(&m_pcoFormatter);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_CREATEFORMATTER);
return E_FAIL;
}
m_pcoFormatter->Initialize(this);
}
*ppiFormatter = m_pcoFormatter;
(*ppiFormatter)->AddRef();
}
__finally
{
Unlock();
}
return S_OK;
}
void CoNumericEditBox::DiscardFormatter()
{
ATLASSERT( m_pcoFormatter && m_pcoFormatter->IsInitialized() );
// Code below is not comletely safe to be used with multithreading.
Lock();
__try
{
m_pcoFormatter->Uninitialize();
m_pcoFormatter = NULL;
}
__finally
{
Unlock();
}
}
HRESULT CoNumericEditBox::_OnRequestEditFormatterParams()
{
if ( m_nFreezeEvents == 0 )
return FireOnRequestEdit(DISPID_FORMATTERPARAMS);
return S_OK;
}
void CoNumericEditBox::_OnFormatterParamsChanged(BOOL bValueTypeChanged,
BOOL bUpdateCtrl)
{
m_bRequiresSave = TRUE;
if ( m_nFreezeEvents == 0 )
FireOnChanged(DISPID_FORMATTERPARAMS);
if ( bUpdateCtrl )
m_ctlEdit._OnFormatterChanged(bValueTypeChanged);
FireViewChange();
SendOnDataChange(NULL);
}
/////////////////////////////////////////////////////////////////////////////////////////
// Implementation: Masked edit event handlers
void CoNumericEditBox::_OnModified()
{
Fire_OnModifyChanged();
}
BOOL CoNumericEditBox::_OnValueChanging(const void* lpcNewValue, BOOL bValid)
{
CComVariant cvtNewValue;
CNumericEditWindow::ConvertValue(m_ctlEdit.GetFormatter().GetValueType(),
lpcNewValue, bValid, &cvtNewValue);
VARIANT_BOOL vbAccepted;
Fire_OnValueChanging(cvtNewValue, &vbAccepted);
return vbAccepted;
}
void CoNumericEditBox::_OnValueChanged()
{
Fire_OnValueChanged();
}
void CoNumericEditBox::_OnError()
{
Fire_OnError();
}
/////////////////////////////////////////////////////////////////////////////////////////
// Helpers
void CoNumericEditBox::DrawBorder(HDC hDC, RECT* prc, BOOL bAdjustRect)
{
if ( !m_ctlEdit._GetBorderVisible() )
return;
const DWORD dwDEParams = ( bAdjustRect ) ? BF_RECT|BF_ADJUST : BF_RECT;
switch( m_ctlEdit._GetAppearance() )
{
case acFlat:
::DrawEdge(hDC, prc, BDR_SUNKENOUTER, dwDEParams|BF_MONO|BF_FLAT|BF_SOFT);
break;
case acSoft:
::DrawEdge(hDC, prc, BDR_SUNKENINNER, dwDEParams|BF_SOFT);
break;
case ac3D:
::DrawEdge(hDC, prc, BDR_SUNKENINNER|BDR_SUNKENOUTER, dwDEParams);
break;
}
}
void CoNumericEditBox::CalcMargins(HDC hDC, LONG* pdxLeft, LONG* pdxRight, LONG* pdyTopBottom)
{
ATLASSERT( !::IsBadWritePtr(pdxLeft, sizeof(LONG)) );
ATLASSERT( !::IsBadWritePtr(pdxRight, sizeof(LONG)) );
ATLASSERT( !::IsBadWritePtr(pdyTopBottom, sizeof(LONG)) );
TEXTMETRIC tm;
GetTextMetrics(hDC, &tm);
if ( tm.tmPitchAndFamily & TMPF_TRUETYPE )
{
ABC abc;
::GetCharABCWidths(hDC, _T('A'), _T('A'), &abc);
*pdxLeft = tm.tmAveCharWidth - abc.abcC;
*pdxRight = tm.tmAveCharWidth - abc.abcA;;
}
else
{
*pdxLeft = tm.tmAveCharWidth - tm.tmOverhang;
*pdxRight = tm.tmAveCharWidth - tm.tmOverhang;
}
if ( *pdxLeft < 0 )
*pdxLeft = 0;
if ( *pdxRight < 0 )
*pdxRight = 0;
*pdyTopBottom = (tm.tmInternalLeading + tm.tmExternalLeading) / 2;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Overrides
BOOL CoNumericEditBox::PreTranslateAccelerator(LPMSG pMsg, HRESULT& hRet)
{
if( pMsg->message == WM_KEYDOWN )
{
switch( pMsg->wParam )
{
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN:
case VK_HOME:
case VK_END:
case VK_NEXT:
case VK_PRIOR:
hRet = S_FALSE;
return TRUE;
}
}
//TODO: Add your additional accelerator handling code here
return FALSE;
}
HRESULT CoNumericEditBox::OnDraw(ATL_DRAWINFO& di)
{
if ( m_ctlEdit.IsWindow() )
return S_OK;
RECT rc = *reinterpret_cast<const RECT*>(di.prcBounds);
// Draw border
DrawBorder(di.hdcDraw, &rc, TRUE);
// Define fore and back colors
COLORREF crFore;
COLORREF crBack;
if ( m_ctlEdit._GetReadOnly() )
{
crFore = m_ctlEdit._GetReadOnlyForeColor();
crBack = m_ctlEdit._GetReadOnlyBackColor();
}
else
{
crFore = m_ctlEdit._GetForeColor();
crBack = m_ctlEdit._GetBackColor();
}
// Draw background
HBRUSH hbrBack = CreateSolidBrush(crBack);
::FillRect(di.hdcDraw, &rc, hbrBack);
::DeleteObject(hbrBack);
// Draw text
HFONT hFont = m_ctlEdit._GetFontHandle();
HFONT hFontOld = (HFONT)::SelectObject(di.hdcDraw, hFont);
LONG dxLeft = 0;
LONG dxRight = 0;
LONG dyTopBottom = 0;
CalcMargins(di.hdcDraw, &dxLeft, &dxRight, &dyTopBottom);
LONG cxWidth = rc.right - rc.left;
if ( cxWidth < dxLeft + dxRight )
{
dxLeft = cxWidth / 2;
dxRight = cxWidth / 2;
}
::InflateRect(&rc, 0, -dyTopBottom);
DWORD fDTOptions = DT_EDITCONTROL|DT_NOPREFIX;
switch( m_ctlEdit._GetAlignment() )
{
case alLeft:
fDTOptions |= DT_LEFT;
break;
case alCenter:
fDTOptions |= DT_CENTER;
break;
case alGeneral:
case alRight:
fDTOptions |= DT_RIGHT;
break;
}
if ( m_ctlEdit._GetRightToLeft() )
{
fDTOptions |= DT_RTLREADING;
}
::SetTextColor(di.hdcDraw, crFore);
::SetBkColor(di.hdcDraw, crBack);
DRAWTEXTPARAMS dtp;
dtp.cbSize = sizeof(DRAWTEXTPARAMS);
dtp.iLeftMargin = dxLeft;
dtp.iRightMargin = dxRight;
dtp.iTabLength = 0;
dtp.uiLengthDrawn = 0;
::DrawTextEx(di.hdcDraw, _T("Sample edit box"), 15, &rc, fDTOptions, &dtp);
// Restore DC font
::SelectObject(di.hdcDraw, hFontOld);
m_ctlEdit._FreeFontHandle(hFont);
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Message handling
LRESULT CoNumericEditBox::OnCtrlCreate(UINT uMsg, WPARAM wParam, LPARAM lParam,
BOOL& bHandled)
{
RECT rc;
GetWindowRect(&rc);
rc.right -= rc.left;
rc.bottom -= rc.top;
rc.top = rc.left = 0;
// Set window styles
DWORD dwStyle = GetWndStyle(0);
DWORD dwExStyle = GetWndExStyle(0);
m_ctlEdit.DefineWindowStyles(&dwStyle, &dwExStyle,
CNumericEditContainedWindow::MES_ALL);
m_ctlEdit.Create(m_hWnd, rc, NULL, dwStyle, dwExStyle);
// Update ReadOnly
m_ctlEdit._OnReadOnlyChanged();
// Update font
m_ctlEdit.UpdateFont();
return 0;
}
LRESULT CoNumericEditBox::OnCtrlSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LRESULT lRes = CComControl<CoNumericEditBox>::OnSetFocus(uMsg, wParam, lParam, bHandled);
if ( m_bInPlaceActive )
{
if( !IsChild(::GetFocus()) )
m_ctlEdit.SetFocus();
}
return lRes;
}
LRESULT CoNumericEditBox::OnCtrlColorEdit(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
ATLASSERT( m_ctlEdit.m_hWnd == (HWND)lParam );
HBRUSH hbrBkg = NULL;
bHandled = m_ctlEdit.UpdateEditDC(reinterpret_cast<HDC>(wParam), &hbrBkg);
return reinterpret_cast<LRESULT>(hbrBkg);
}
LRESULT CoNumericEditBox::OnCtrlColorStatic(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
ATLASSERT( m_ctlEdit.m_hWnd == (HWND)lParam );
HBRUSH hbrBkg = NULL;
bHandled = m_ctlEdit.UpdateStaticDC(reinterpret_cast<HDC>(wParam), &hbrBkg);
return reinterpret_cast<LRESULT>(hbrBkg);
}
LRESULT CoNumericEditBox::OnCtrlEditChange(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
if ( m_ctlEdit._GetEditing() )
{
bool bModifyWnd = m_ctlEdit.SendMessage(EM_GETMODIFY) != FALSE;
bool bModifyCtl = m_ctlEdit._GetModify() != FALSE;
if ( bModifyWnd != bModifyCtl )
{
m_ctlEdit._SetModify(bModifyWnd);
_OnModified();
}
}
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Message handling (subclassing window procedure)
LRESULT CoNumericEditBox::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
bHandled = FALSE;
BOOL bResult = m_ctlEdit.BeginEdit();
ATLASSERT( bResult );
if ( !bResult )
{
_OnError();
}
return 0;
}
LRESULT CoNumericEditBox::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
bHandled = FALSE;
BOOL bResult = m_ctlEdit.EndEdit();
ATLASSERT( bResult );
if ( !bResult )
{
_OnError();
}
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Implementation: ISupportErrorInfo
STDMETHODIMP CoNumericEditBox::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_INumericEditBox,
&IID_IPersist,
&IID_IPersistStreamInit,
&IID_IPersistStorage
};
for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
{
if ( InlineIsEqualGUID(*arr[i], riid) )
return S_OK;
}
return S_FALSE;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Implementation: IOleInPlaceObjectWindowless
STDMETHODIMP CoNumericEditBox::SetObjectRects(LPCRECT prcPos,LPCRECT prcClip)
{
IOleInPlaceObjectWindowlessImpl<CoNumericEditBox>::SetObjectRects(prcPos, prcClip);
int cx = prcPos->right - prcPos->left;
int cy = prcPos->bottom - prcPos->top;
::SetWindowPos(m_ctlEdit.m_hWnd, NULL, 0, 0, cx, cy, SWP_NOZORDER|SWP_NOACTIVATE);
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Operations: Persistence
void CoNumericEditBox::_Persist_ReportLastError(HRESULT hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_IPersist, hr, LPCTSTR(NULL), 0);
}
HRESULT CoNumericEditBox::_Persist_InitNew()
{
ATLASSERT( !m_ctlEdit.IsWindow() );
ATLASSERT( m_pcoFontNS && !m_pcoFontNS->GetCookie() );
// Appearance
short nAppearance;
HRESULT hr = GetAmbientAppearance(nAppearance);
if ( SUCCEEDED(hr) )
{
if ( nAppearance )
m_ctlEdit._SetAppearance(ac3D);
else
m_ctlEdit._SetAppearance(acFlat);
}
else
{
m_ctlEdit._SetAppearance(ac3D);
}
// Alignment
SHORT shAlignment;
hr = GetAmbientTextAlign(shAlignment);
if ( FAILED(hr) )
shAlignment = 0;
m_ctlEdit._SetAlignment(static_cast<AlignmentConstants>(shAlignment));
// Font
CComPtr<IFont> spiAmbientFont;
hr = GetAmbientFont(&spiAmbientFont);
if ( SUCCEEDED(hr) )
{
ATLASSERT( spiAmbientFont );
hr = m_ctlEdit._SetFontCopy(spiAmbientFont);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_INITFONT);
return E_FAIL;
}
}
else
{
HFONT hFont = reinterpret_cast<HFONT>(::GetStockObject(DEFAULT_GUI_FONT));
hr = m_ctlEdit._SetFontHandle(hFont);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_INITFONT);
return E_FAIL;
}
}
ATLASSERT( m_ctlEdit._GetRefFont() );
hr = m_pcoFontNS->Advise(m_ctlEdit._GetRefFont());
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_INITFONT);
return E_FAIL;
}
// We should not use GetAmbientForeColor and GetAmbientBackColor to get
// fore and back colors for edit control.
m_ctlEdit._SetForeOleColor(0x80000000 | COLOR_WINDOWTEXT);
m_ctlEdit._SetBackOleColor(0x80000000 | COLOR_WINDOW);
m_ctlEdit._SetReadOnlyForeOleColor(0x80000000 | COLOR_BTNTEXT);
m_ctlEdit._SetReadOnlyBackOleColor(0x80000000 | COLOR_BTNFACE);
// RightToLeft
BOOL bRightToLeft = FALSE;
BOOL bRightAlignment = FALSE;
hr = GetAmbientRightToLeft(bRightToLeft);
if ( SUCCEEDED(hr) )
{
bRightAlignment = bRightToLeft;
}
/*
else
{
DWORD fLayout;
if ( ::GetProcessDefaultLayout(&fLayout) )
{
bRightToLeft = fLayout & WS_EX_RTLREADING;
bRightAlignment = fLayout & WS_EX_RIGHT;
}
}
*/
m_ctlEdit._SetRightToLeft(bRightToLeft);
// Set default size
SIZEL size = { 150, 23 };
AtlPixelToHiMetric(&size, &m_sizeExtent);
// GetAmbientLocaleID
// GetAmbientCodePage
// GetAmbientCharSet
// GetAmbientTopToBottom
// GetAmbientUserMode(
// DISPID_AMBIENT_SHOWGRABHANDLES
// GetAmbientSupportsMnemonics
// GetAmbientPalette
// Configure formatter by default
hr = m_ctlEdit.GetFormatter().Configure(vtInt32, ftNumeric);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_CONFIGUREOLEFORMATTER);
return hr;
}
return S_OK;
}
void CoNumericEditBox::_PersistStream_ReportLastError(HRESULT hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_IPersistStream, hr,
LPCTSTR(NULL), 0);
}
HRESULT CoNumericEditBox::_PersistStream_GetSizeMax(ULARGE_INTEGER* pcbSize)
{
ATLASSERT( !::IsBadWritePtr(pcbSize, sizeof(ULARGE_INTEGER)) );
pcbSize->HighPart = 0;
// Add size of the ATL version we write out.
pcbSize->LowPart = sizeof(DWORD);
// Add size of control extent.
pcbSize->LowPart += sizeof(SIZE);
// Add size of appearance.
pcbSize->LowPart += sizeof(AppearanceConstants);
// Add size of BorderVisible.
pcbSize->LowPart += sizeof(VARIANT_BOOL);
// AlignmentConstants
pcbSize->LowPart += sizeof(AlignmentConstants);
// Add size of ForeColor, BackColor, ReadOnlyForeColor, ReadOnlyBackColor.
pcbSize->LowPart += sizeof(OLE_COLOR) * 4;
// Add size of Font object
CComVariant cvtFont(m_ctlEdit._GetRefFont());
pcbSize->LowPart += cvtFont.GetSize();
// Add size of ReadOnly.
pcbSize->LowPart += sizeof(VARIANT_BOOL);
// Add size of RightToLeft.
pcbSize->LowPart += sizeof(VARIANT_BOOL);
// Add size of Modify
pcbSize->LowPart += sizeof(VARIANT_BOOL);
// Add size of Formatter parameters
CComPtr<IFormatter> spiFormatter;
HRESULT hr = get_Formatter(&spiFormatter);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountComError(SP::AE_SETLOG|SP::AE_SETMSG, 1, hr,
static_cast<INumericEditBox*>(this), IID_INumericEditBox);
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 2,
IDS_EROW_GETFORMATTER);
return hr;
}
ATLASSERT( m_pcoFormatter );
ULARGE_INTEGER cbSize;
hr = m_pcoFormatter->_PersistStream_GetSizeMax(&cbSize);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG, IDS_ELS_SPNUMERICEDITBOX, 2,
IDS_ERCC_GETSIZEFORMATTER);
return hr;
}
pcbSize->LowPart += cbSize.LowPart;
return S_OK;
}
HRESULT CoNumericEditBox::_PersistStream_Load(LPSTREAM piStream)
{
ATLASSERT( piStream );
VARIANT_BOOL vbValue;
OLE_COLOR oleClr;
// Check version
DWORD dwVer;
HRESULT hr = piStream->Read(&dwVer, sizeof(DWORD), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADATLVERSION);
return hr;
}
if ( dwVer > _ATL_VER )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_INCORRECTATLVERSION);
return E_FAIL;
}
// Read size of control extents.
hr = piStream->Read(&m_sizeExtent, sizeof(SIZE), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADCTRLEXTENT);
return hr;
}
// Read Appearance.
AppearanceConstants enAppearance;
hr = piStream->Read(&enAppearance, sizeof(AppearanceConstants), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADAPPEARANCE);
return hr;
}
m_ctlEdit._SetAppearance(enAppearance);
// Read BorderVisible.
hr = piStream->Read(&vbValue, sizeof(VARIANT_BOOL), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADBORDERVISIBLE);
return hr;
}
m_ctlEdit._SetBorderVisible(vbValue == VARIANT_TRUE);
// Read AlignmentConstants
AlignmentConstants enAlignment;
hr = piStream->Read(&enAlignment, sizeof(AlignmentConstants), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADALIGNMENT);
return hr;
}
m_ctlEdit._SetAlignment(enAlignment);
// Read ForeColor
hr = piStream->Read(&oleClr, sizeof(OLE_COLOR), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADFORECOLOR);
return hr;
}
m_ctlEdit._SetForeOleColor(oleClr);
// Read BackColor
hr = piStream->Read(&oleClr, sizeof(OLE_COLOR), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADBACKCOLOR);
return hr;
}
m_ctlEdit._SetBackOleColor(oleClr);
// Read ReadOnlyForeColor
hr = piStream->Read(&oleClr, sizeof(OLE_COLOR), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADREADONLYFORECOLOR);
return hr;
}
m_ctlEdit._SetReadOnlyForeColor(oleClr);
// Read ReadOnlyBackColor
hr = piStream->Read(&oleClr, sizeof(OLE_COLOR), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADREADONLYBACKCOLOR);
return hr;
}
m_ctlEdit._SetReadOnlyBackColor(oleClr);
// Read Font object
CComVariant cvtFont;
hr = cvtFont.ReadFromStream(piStream);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADFONT);
return hr;
}
hr = cvtFont.ChangeType(VT_UNKNOWN);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADFONT);
return hr;
}
CComPtr<IFont> spiFont;
if ( cvtFont.punkVal )
{
hr = cvtFont.punkVal->QueryInterface(IID_IFont, (void**)(&spiFont));
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADFONT);
return hr;
}
}
m_ctlEdit._SetFont(spiFont);
// Read ReadOnly.
hr = piStream->Read(&vbValue, sizeof(VARIANT_BOOL), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADREADONLY);
return hr;
}
m_ctlEdit._SetReadOnly(vbValue == VARIANT_TRUE);
// Read RightToLeft
hr = piStream->Read(&vbValue, sizeof(VARIANT_BOOL), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADRIGHTTOLEFT);
return hr;
}
m_ctlEdit._SetRightToLeft(vbValue == VARIANT_TRUE);
// ErrorSymbol
CComBSTR cbsErrorSymbol;
hr = cbsErrorSymbol.ReadFromStream(piStream);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADERRORSYMBOL);
return hr;
}
hr = m_ctlEdit._SetErrorOleSymbol(cbsErrorSymbol);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_EROW_SETERRORSYMBOL);
return hr;
}
// Read Formatter parameters
CComPtr<IFormatter> spiFormatter;
hr = get_Formatter(&spiFormatter);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountComError(SP::AE_SETLOG|SP::AE_SETMSG, 1, hr,
static_cast<INumericEditBox*>(this), IID_INumericEditBox);
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_EROW_GETFORMATTER);
return hr;
}
ATLASSERT( m_pcoFormatter );
hr = m_pcoFormatter->_PersistStream_Load(piStream);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_LOADFORMATTER);
return hr;
}
m_bRequiresSave = FALSE;
return S_OK;
}
HRESULT CoNumericEditBox::_PersistStream_Save(LPSTREAM piStream, BOOL fClearDirty)
{
ATLASSERT( piStream );
VARIANT_BOOL vbValue;
OLE_COLOR oleClr;
// Write ATL version.
const DWORD dw = _ATL_VER;
HRESULT hr = piStream->Write(&dw, sizeof(DWORD), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_SAVEATLVERSION);
return hr;
}
// Write control extent.
hr = piStream->Write(&m_sizeExtent, sizeof(SIZE), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_SAVECTRLEXTENT);
return hr;
}
// Write Appearance.
AppearanceConstants enAppearance = m_ctlEdit._GetAppearance();
hr = piStream->Write(&enAppearance, sizeof(AppearanceConstants), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_SAVEAPPEARANCE);
return hr;
}
// Write BorderVisible.
vbValue = m_ctlEdit._GetBorderVisible() ? VARIANT_TRUE : VARIANT_FALSE;
hr = piStream->Write(&vbValue, sizeof(VARIANT_BOOL), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_SAVEBORDERVISIBLE);
return hr;
}
// Write AlignmentConstants
AlignmentConstants enAlignment = m_ctlEdit._GetAlignment();
hr = piStream->Write(&enAlignment, sizeof(AlignmentConstants), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_SAVEALIGNMENT);
return hr;
}
// Write ForeColor
oleClr = m_ctlEdit._GetForeColor();
hr = piStream->Write(&oleClr, sizeof(OLE_COLOR), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_SAVEFORECOLOR);
return hr;
}
// Write BackColor
oleClr = m_ctlEdit._GetBackColor();
hr = piStream->Write(&oleClr, sizeof(OLE_COLOR), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_SAVEBACKCOLOR);
return hr;
}
// Write ReadOnlyForeColor
oleClr = m_ctlEdit._GetReadOnlyForeColor();
hr = piStream->Write(&oleClr, sizeof(OLE_COLOR), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_SAVEREADONLYFORECOLOR);
return hr;
}
// Write ReadOnlyBackColor
oleClr = m_ctlEdit._GetReadOnlyBackColor();
hr = piStream->Write(&oleClr, sizeof(OLE_COLOR), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_SAVEREADONLYBACKCOLOR);
return hr;
}
// Write Font object
CComVariant cvtFont = m_ctlEdit._GetRefFont();
hr = cvtFont.WriteToStream(piStream);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_SAVEFONT);
return hr;
}
// Write ReadOnly.
vbValue = m_ctlEdit._GetReadOnly() ? VARIANT_TRUE : VARIANT_FALSE;
hr = piStream->Write(&vbValue, sizeof(VARIANT_BOOL), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_SAVEREADONLY);
return hr;
}
// Write RightToLeft.
vbValue = m_ctlEdit._GetRightToLeft() ? VARIANT_TRUE : VARIANT_FALSE;
hr = piStream->Write(&vbValue, sizeof(VARIANT_BOOL), NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_SAVERIGHTTOLEFT);
return hr;
}
// ErrorSymbol
CComBSTR cbsErrorSymbol;
hr = m_ctlEdit._GetErrorOleSymbol(&cbsErrorSymbol);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_EROW_GETERRORSYMBOL);
return hr;
}
hr = cbsErrorSymbol.WriteToStream(piStream);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_SAVEERRORSYMBOL);
return hr;
}
// Write Formatter parameters
CComPtr<IFormatter> spiFormatter;
hr = get_Formatter(&spiFormatter);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountComError(SP::AE_SETLOG|SP::AE_SETMSG, 1, hr,
static_cast<INumericEditBox*>(this), IID_INumericEditBox);
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_EROW_GETFORMATTER);
return hr;
}
ATLASSERT( m_pcoFormatter );
hr = m_pcoFormatter->_PersistStream_Save(piStream, fClearDirty);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCC_SAVEFORMATTER);
return hr;
}
// if ( fClearDirty )
// m_bRequiresSave = FALSE;
return S_OK;
}
void CoNumericEditBox::_PersistStorage_ReportLastError(HRESULT hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_IPersistStorage, hr,
LPCTSTR(NULL), 0);
}
HRESULT CoNumericEditBox::_PersistStorage_InitNew(IStorage* piStorage)
{
return _Persist_InitNew();
}
HRESULT CoNumericEditBox::_PersistStorage_Load(IStorage* piStorage)
{
LPCOLESTR lpcszContents = OLESTR("Contents");
const DWORD fOptions = STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
CComPtr<IStream> spiStream;
HRESULT hr = piStorage->OpenStream(lpcszContents, NULL, fOptions, 0, &spiStream);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
{
SP::AccountComError(SP::AE_SETLOG|SP::AE_SETMSG, 1, hr, piStorage, IID_IStorage);
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 2,
IDS_ERCC_OPENTREAMINSTORAGE);
return hr;
}
return _PersistStream_Load(spiStream);
}
HRESULT CoNumericEditBox::_PersistStorage_Save(IStorage* piStorage, BOOL fSameAsLoad)
{
LPCOLESTR lpcszContents = OLESTR("Contents");
const DWORD fOptions = STGM_READWRITE|STGM_SHARE_EXCLUSIVE|STGM_CREATE;
CComPtr<IStream> spiStream;
HRESULT hr = piStorage->CreateStream(lpcszContents, fOptions, 0, 0, &spiStream);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
{
SP::AccountComError(SP::AE_SETLOG|SP::AE_SETMSG, 1, hr, piStorage, IID_IStorage);
SP::AccountError(SP::AE_LOG|SP::AE_ADDMSG, IDS_ELS_SPNUMERICEDITBOX, 2,
IDS_ERCC_CREATESTREAMINSTORAGE);
return hr;
}
return _PersistStream_Save(spiStream, fSameAsLoad);
}
HRESULT CoNumericEditBox::_PersistStorage_SaveCompleted(IStorage* piStorage)
{
return S_OK;
}
HRESULT CoNumericEditBox::_PersistStorage_HandsOffStorage()
{
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Implementation: INumericEditBox
// Appearance
STDMETHODIMP CoNumericEditBox::get_Appearance(AppearanceConstants* penAppearance)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_Appearance\n") );
ATLASSERT( !::IsBadWritePtr(penAppearance, sizeof(AppearanceConstants)) );
if ( !penAppearance )
return E_POINTER;
*penAppearance = m_ctlEdit._GetAppearance();
return S_OK;
}
STDMETHODIMP CoNumericEditBox::put_Appearance(AppearanceConstants enAppearance)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::put_Appearance\n") );
if ( m_nFreezeEvents == 0 && FireOnRequestEdit(DISPID_APPEARANCE) == S_FALSE )
return S_FALSE;
m_ctlEdit._SetAppearance(enAppearance);
m_bRequiresSave = TRUE;
if ( m_nFreezeEvents == 0 )
FireOnChanged(DISPID_APPEARANCE);
m_ctlEdit._OnAppearanceChanged();
FireViewChange();
SendOnDataChange(NULL);
return S_OK;
}
// BorderVisible
STDMETHODIMP CoNumericEditBox::get_BorderVisible(VARIANT_BOOL* pvbValue)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_TabStop\n") );
ATLASSERT( !::IsBadWritePtr(pvbValue, sizeof(VARIANT_BOOL)) );
if ( !pvbValue )
return E_POINTER;
*pvbValue = m_ctlEdit._GetBorderVisible() ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE;
return S_OK;
}
STDMETHODIMP CoNumericEditBox::put_BorderVisible(VARIANT_BOOL vbValue)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::put_TabStop\n") );
if ( m_nFreezeEvents == 0 && FireOnRequestEdit(DISPID_TABSTOP) == S_FALSE )
return S_FALSE;
m_ctlEdit._SetBorderVisible(vbValue);
m_bRequiresSave = TRUE;
if ( m_nFreezeEvents == 0 )
FireOnChanged(DISPID_TABSTOP);
m_ctlEdit._OnBorderVisibleChanged();
FireViewChange();
SendOnDataChange(NULL);
return S_OK;
}
// Alignment
STDMETHODIMP CoNumericEditBox::get_Alignment(AlignmentConstants* penValue)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_Alignment\n") );
ATLASSERT( !::IsBadWritePtr(penValue, sizeof(AlignmentConstants)) );
if ( !penValue )
return E_POINTER;
*penValue = m_ctlEdit._GetAlignment();
return S_OK;
}
STDMETHODIMP CoNumericEditBox::put_Alignment(AlignmentConstants enValue)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::put_Alignment\n") );
BOOL bUserMode;
HRESULT hr = GetAmbientUserMode(bUserMode);
if ( SUCCEEDED(hr) && bUserMode && IsWindow() )
{
SP::ReportErrorWithCom(SP::AE_LOG|SP::AE_SETMSG, GetObjectCLSID(),
IID_INumericEditBox, E_UNEXPECTED,
IDS_ELS_SPCONVERSION, 0,
IDS_ERCC_CANNOTCHANGEALIGNMENT);
return E_UNEXPECTED;
}
if ( m_nFreezeEvents == 0 && FireOnRequestEdit(DISPID_ALIGNMENT) == S_FALSE )
return S_FALSE;
m_ctlEdit._SetAlignment(enValue);
m_bRequiresSave = TRUE;
if ( m_nFreezeEvents == 0 )
FireOnChanged(DISPID_ALIGNMENT);
m_ctlEdit._OnAlignmentChanged();
FireViewChange();
SendOnDataChange(NULL);
return S_OK;
}
// ForeColor
STDMETHODIMP CoNumericEditBox::get_ForeColor(OLE_COLOR* poleColor)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_ForeColor\n") );
if ( !poleColor )
return E_POINTER;
*poleColor = m_ctlEdit._GetForeOleColor();
return S_OK;
}
STDMETHODIMP CoNumericEditBox::put_ForeColor(OLE_COLOR oleColor)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::put_ForeColor\n") );
if ( m_nFreezeEvents == 0 && FireOnRequestEdit(DISPID_FORECOLOR) == S_FALSE )
return S_FALSE;
m_ctlEdit._SetForeOleColor(oleColor);
m_bRequiresSave = TRUE;
if ( m_nFreezeEvents == 0 )
FireOnChanged(DISPID_FORECOLOR);
m_ctlEdit._OnForeColorChanged();
FireViewChange();
SendOnDataChange(NULL);
return S_OK;
}
// BackColor
STDMETHODIMP CoNumericEditBox::get_BackColor(OLE_COLOR* poleColor)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_BackColor\n") );
if ( !poleColor )
return E_POINTER;
*poleColor = m_ctlEdit._GetBackOleColor();
return S_OK;
}
STDMETHODIMP CoNumericEditBox::put_BackColor(OLE_COLOR oleColor)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::put_BackColor\n") );
if ( m_nFreezeEvents == 0 && FireOnRequestEdit(DISPID_BACKCOLOR) == S_FALSE )
return S_FALSE;
m_ctlEdit._SetBackOleColor(oleColor);
m_bRequiresSave = TRUE;
if ( m_nFreezeEvents == 0 )
FireOnChanged(DISPID_BACKCOLOR);
m_ctlEdit._OnBackColorChanged();
FireViewChange();
SendOnDataChange(NULL);
return S_OK;
}
// ReadOnlyForeColor
STDMETHODIMP CoNumericEditBox::get_ReadOnlyForeColor(OLE_COLOR* poleColor)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_ReadOnlyForeColor\n") );
if ( !poleColor )
return E_POINTER;
*poleColor = m_ctlEdit._GetReadOnlyForeOleColor();
return S_OK;
}
STDMETHODIMP CoNumericEditBox::put_ReadOnlyForeColor(OLE_COLOR oleColor)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::put_ReadOnlyForeColor\n") );
if ( m_nFreezeEvents == 0 && FireOnRequestEdit(DISPID_READONLYFORECOLOR) == S_FALSE )
return S_FALSE;
m_ctlEdit._SetReadOnlyForeOleColor(oleColor);
m_bRequiresSave = TRUE;
if ( m_nFreezeEvents == 0 )
FireOnChanged(DISPID_READONLYFORECOLOR);
m_ctlEdit._OnReadOnlyForeColorChanged();
FireViewChange();
SendOnDataChange(NULL);
return S_OK;
}
// ReadOnlyBackColor
STDMETHODIMP CoNumericEditBox::get_ReadOnlyBackColor(OLE_COLOR* poleColor)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_ReadOnlyBackColor\n") );
if ( !poleColor )
return E_POINTER;
*poleColor = m_ctlEdit._GetReadOnlyBackOleColor();
return S_OK;
}
STDMETHODIMP CoNumericEditBox::put_ReadOnlyBackColor(OLE_COLOR oleColor)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::put_ReadOnlyBackColor\n") );
if ( m_nFreezeEvents == 0 && FireOnRequestEdit(DISPID_READONLYBACKCOLOR) == S_FALSE )
return S_FALSE;
m_ctlEdit._SetReadOnlyBackOleColor(oleColor);
m_bRequiresSave = TRUE;
if ( m_nFreezeEvents == 0 )
FireOnChanged(DISPID_READONLYBACKCOLOR);
m_ctlEdit._OnReadOnlyBackColorChanged();
FireViewChange();
SendOnDataChange(NULL);
return S_OK;
}
// Font
STDMETHODIMP CoNumericEditBox::get_Font(IFontDisp** ppiFont)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_Font\n") );
return m_ctlEdit._GetFontDisp(ppiFont);
}
STDMETHODIMP CoNumericEditBox::put_Font(IFontDisp* piFont)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::put_Font\n") );
ATLASSERT( m_pcoFontNS );
if ( m_nFreezeEvents == 0 && FireOnRequestEdit(DISPID_FONT) == S_FALSE )
return S_FALSE;
m_ctlEdit._OnFontChanging();
// Disconnect property notify sink
if ( m_pcoFontNS->GetCookie() )
m_pcoFontNS->Unadvise(m_ctlEdit._GetRefFont());
HRESULT hr = m_ctlEdit._SetCopyFontDisp(piFont);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return hr;
}
m_bRequiresSave = TRUE;
// Connect property notify sink
if ( m_ctlEdit._GetRefFont() )
{
hr = m_pcoFontNS->Advise(m_ctlEdit._GetRefFont());
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return E_FAIL;
}
}
if ( m_nFreezeEvents == 0 )
FireOnChanged(DISPID_FONT);
m_ctlEdit._OnFontChanged();
FireViewChange();
SendOnDataChange(NULL);
return S_OK;
}
STDMETHODIMP CoNumericEditBox::putref_Font(IFontDisp* piFont)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::piFont\n") );
ATLASSERT( m_pcoFontNS );
if ( m_nFreezeEvents == 0 && FireOnRequestEdit(DISPID_FONT) == S_FALSE )
return S_FALSE;
m_ctlEdit._OnFontChanging();
// Disconnect property notify sink
if ( m_pcoFontNS->GetCookie() )
m_pcoFontNS->Unadvise(m_ctlEdit._GetRefFont());
HRESULT hr = m_ctlEdit._SetFontDisp(piFont);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return hr;
}
m_bRequiresSave = TRUE;
// Connect property notify sink
if ( m_ctlEdit._GetRefFont() )
{
hr = m_pcoFontNS->Advise(m_ctlEdit._GetRefFont());
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return E_FAIL;
}
}
if ( m_nFreezeEvents == 0 )
FireOnChanged(DISPID_FONT);
m_ctlEdit._OnFontChanged();
FireViewChange();
SendOnDataChange(NULL);
return S_OK;
}
// ReadOnly
STDMETHODIMP CoNumericEditBox::get_ReadOnly(VARIANT_BOOL* pvbValue)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_ReadOnly\n") );
ATLASSERT( !::IsBadWritePtr(pvbValue, sizeof(VARIANT_BOOL)) );
if ( !pvbValue )
return E_POINTER;
*pvbValue = m_ctlEdit._GetReadOnly() ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE;
return S_OK;
}
STDMETHODIMP CoNumericEditBox::put_ReadOnly(VARIANT_BOOL vbValue)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::put_ReadOnly\n") );
if ( m_nFreezeEvents == 0 && FireOnRequestEdit(DISPID_READONLY) == S_FALSE )
return S_FALSE;
m_ctlEdit._SetReadOnly(vbValue);
m_bRequiresSave = TRUE;
if ( m_nFreezeEvents == 0 )
FireOnChanged(DISPID_READONLY);
m_ctlEdit._OnReadOnlyChanged();
FireViewChange();
SendOnDataChange(NULL);
return S_OK;
}
// RightToLeft
STDMETHODIMP CoNumericEditBox::get_RightToLeft(VARIANT_BOOL* pvbValue)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_RightToLeft\n") );
ATLASSERT( !::IsBadWritePtr(pvbValue, sizeof(VARIANT_BOOL)) );
if ( !pvbValue )
return E_POINTER;
*pvbValue = m_ctlEdit._GetRightToLeft() ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE;
return S_OK;
}
STDMETHODIMP CoNumericEditBox::put_RightToLeft(VARIANT_BOOL vbValue)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::put_ReadOnly\n") );
if ( m_nFreezeEvents == 0 && FireOnRequestEdit(DISPID_RIGHTTOLEFT) == S_FALSE )
return S_FALSE;
m_ctlEdit._SetRightToLeft(vbValue);
m_bRequiresSave = TRUE;
if ( m_nFreezeEvents == 0 )
FireOnChanged(DISPID_RIGHTTOLEFT);
m_ctlEdit._OnRightToLeftChanged();
FireViewChange();
SendOnDataChange(NULL);
return S_OK;
}
// ErrorSymbol
STDMETHODIMP CoNumericEditBox::get_ErrorSymbol(BSTR* pbsErrorSymbol)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_ErrorSymbol\n") );
ATLASSERT( !::IsBadWritePtr(pbsErrorSymbol, sizeof(BSTR)) );
if ( !pbsErrorSymbol )
return E_POINTER;
HRESULT hr = m_ctlEdit._GetErrorOleSymbol(pbsErrorSymbol);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return hr;
}
return S_OK;
}
STDMETHODIMP CoNumericEditBox::put_ErrorSymbol(BSTR bsErrorSymbol)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::put_ErrorSymbol\n") );
if ( m_nFreezeEvents == 0 && FireOnRequestEdit(DISPID_ERRORSYMBOL) == S_FALSE )
return S_FALSE;
HRESULT hr = m_ctlEdit._SetErrorOleSymbol(bsErrorSymbol);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return hr;
}
m_bRequiresSave = TRUE;
if ( m_nFreezeEvents == 0 )
FireOnChanged(DISPID_ERRORSYMBOL);
m_ctlEdit._OnErrorSymbolChanged();
FireViewChange();
SendOnDataChange(NULL);
return S_OK;
}
// Formatter Params
STDMETHODIMP CoNumericEditBox::get_FormatterParams(BSTR* pbsParams)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_FormatterParams\n") );
ATLASSERT( !::IsBadWritePtr(pbsParams, sizeof(BSTR)) );
if ( !pbsParams )
return E_POINTER;
ValueTypeConstants enValueType = m_ctlEdit.GetFormatter().GetValueType();
FormatTypeConstants enFormatType = m_ctlEdit.GetFormatter().GetFormatType();
CComBSTR cbsDisplayMask;
HRESULT hr = m_ctlEdit.GetFormatter().GetOleMask(FM_DISPLAY, &cbsDisplayMask);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return hr;
}
CComBSTR cbsEditingMask;
hr = m_ctlEdit.GetFormatter().GetOleMask(FM_EDITING, &cbsEditingMask);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return hr;
}
hr = BuildFormatterParamString(enValueType, enFormatType, cbsDisplayMask, cbsEditingMask,
pbsParams);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return hr;
}
return S_OK;
}
STDMETHODIMP CoNumericEditBox::put_FormatterParams(BSTR bsParams)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::put_FormatterParams\n") );
if ( m_nFreezeEvents == 0 && FireOnRequestEdit(DISPID_FORMATTERPARAMS) == S_FALSE )
return S_FALSE;
ValueTypeConstants enValueType;
FormatTypeConstants enFormatType;
CComBSTR cbsDisplayMask;
CComBSTR cbsEditingMask;
HRESULT hr = ParseFormatterParamString(bsParams, &enValueType, &enFormatType,
&cbsDisplayMask, &cbsEditingMask);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return hr;
}
ValueTypeConstants enOldValueType = m_ctlEdit.GetFormatter().GetValueType();
// Set new formatter properties
hr = m_ctlEdit.GetFormatter().Configure(enValueType, enFormatType,
cbsDisplayMask, cbsEditingMask);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return hr;
}
m_ctlEdit._OnFormatterChanged(enOldValueType != enValueType);
m_bRequiresSave = TRUE;
if ( m_nFreezeEvents == 0 )
FireOnChanged(DISPID_FORMATTERPARAMS);
FireViewChange();
SendOnDataChange(NULL);
return S_OK;
}
// Formatter
STDMETHODIMP CoNumericEditBox::get_Formatter(IFormatter** ppiFormatter)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_Formatter\n") );
if ( !ppiFormatter )
return E_POINTER;
HRESULT hr = GetFormatter(ppiFormatter);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return E_FAIL;
}
return S_OK;
}
// HWND
STDMETHODIMP CoNumericEditBox::get_HWND(LONG_PTR* phWnd)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_HWND\n") );
ATLASSERT( !::IsBadWritePtr(phWnd, sizeof(LONG_PTR)) );
if ( !phWnd )
return E_POINTER;
*phWnd = m_ctlEdit.IsWindow() ? reinterpret_cast<LONG_PTR>(m_ctlEdit.m_hWnd) : NULL;
return S_OK;
}
// Modify
STDMETHODIMP CoNumericEditBox::get_Modify(VARIANT_BOOL* pvbModify)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_Modify\n") );
ATLASSERT( !::IsBadWritePtr(pvbModify, sizeof(VARIANT_BOOL)) );
if ( !pvbModify )
return E_POINTER;
*pvbModify = m_ctlEdit._GetModify() ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE;
return S_OK;
}
STDMETHODIMP CoNumericEditBox::put_Modify(VARIANT_BOOL vbModify)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::put_Modify\n") );
m_ctlEdit._SetModify(vbModify);
m_ctlEdit._OnModifyChanged();
return S_OK;
}
// Value
STDMETHODIMP CoNumericEditBox::get_Value(VARIANT* pvValue)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_Value\n") );
if ( !pvValue )
return E_POINTER;
HRESULT hr = m_ctlEdit.GetOleValue(pvValue);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return E_FAIL;
}
return S_OK;
}
STDMETHODIMP CoNumericEditBox::put_Value(VARIANT vValue)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::put_Value\n") );
if ( m_nFreezeEvents == 0 && FireOnRequestEdit(DISPID_VALUE) == S_FALSE )
return S_FALSE;
while ( vValue.vt == (VT_BYREF|VT_VARIANT) )
{
CComVariant cvtTemp = *vValue.pvarVal;
vValue = cvtTemp;
}
HRESULT hr = m_ctlEdit.SetOleValue(vValue);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return E_FAIL;
}
m_bRequiresSave = TRUE;
if ( m_nFreezeEvents == 0 )
FireOnChanged(DISPID_VALUE);
m_ctlEdit._OnValueChanged();
FireViewChange();
SendOnDataChange(NULL);
return S_OK;
}
// Display Text
STDMETHODIMP CoNumericEditBox::get_DisplayText(BSTR* pbsText)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_DisplayText\n") );
if ( !pbsText )
return E_POINTER;
HRESULT hr = m_ctlEdit.GetDisplayOleText(pbsText);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return E_FAIL;
}
return S_OK;
}
// Edit Text
STDMETHODIMP CoNumericEditBox::get_EditingText(BSTR* pbsText)
{
ATLTRACE( ATL::atlTraceControls, 2, _T("CoNumericEditBox::get_EditingText\n") );
if ( !pbsText )
return E_POINTER;
HRESULT hr = m_ctlEdit.GetEditingOleText(pbsText);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
{
SP::ReportErrorWithCom(0, GetObjectCLSID(), IID_INumericEditBox, hr,
LPCTSTR(NULL), 0);
return E_FAIL;
}
return S_OK;
}