📄 ctlprop.cpp
字号:
{
// Can be overridden by subclass
InvalidateControl();
}
/////////////////////////////////////////////////////////////////////////////
// BorderStyle property
short COleControl::GetBorderStyle()
{
return m_sBorderStyle;
}
void COleControl::SetBorderStyle(short sBorderStyle)
{
if (sBorderStyle != 0 && sBorderStyle != 1)
ThrowError(CTL_E_INVALIDPROPERTYVALUE, AFX_IDP_E_INVALIDPROPERTYVALUE);
// Is the property changing?
if (m_sBorderStyle == sBorderStyle)
return;
if (!BoundPropertyRequestEdit(DISPID_BORDERSTYLE))
SetNotPermitted();
ASSERT((m_hWnd == NULL) ||
((GetStyle() & WS_BORDER) == (DWORD)(m_sBorderStyle ? WS_BORDER : 0)));
m_sBorderStyle = sBorderStyle;
m_bModified = TRUE;
_AfxToggleBorderStyle(this);
OnBorderStyleChanged();
BoundPropertyChanged(DISPID_BORDERSTYLE);
}
void COleControl::OnBorderStyleChanged()
{
// Can be overridden by subclass
InvalidateControl();
}
/////////////////////////////////////////////////////////////////////////////
// Text and Caption properties
const CString& COleControl::InternalGetText()
{
// Some subclassed controls (such as edit controls and comboboxes) change
// the window text without sending WM_SETTEXT. Therefore, we need to
// ensure that m_strText is up-to-date.
if (m_hWnd != NULL && IsSubclassedControl())
{
// Usually, the window text will be shorter than 32 characters.
// When it is, we can be more efficient.
const int _cchUsual = 32;
if (DefWindowProc(WM_GETTEXT, (WPARAM)_cchUsual,
(LPARAM)m_strText.GetBufferSetLength(_cchUsual)) >= _cchUsual - 1)
{
// Text was too long: allocate a bigger buffer.
int nLen = DefWindowProc(WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) + 1;
DefWindowProc(WM_GETTEXT, (WPARAM)nLen,
(LPARAM)m_strText.GetBufferSetLength(nLen));
}
m_strText.ReleaseBuffer();
}
return m_strText;
}
BSTR COleControl::GetText()
{
return ((CString&)InternalGetText()).AllocSysString();
}
void COleControl::SetText(LPCTSTR pszText)
{
LRESULT lResult;
if (m_hWnd != NULL)
lResult = SendMessage(WM_SETTEXT, 0, (LPARAM)pszText);
else
lResult = OnSetText(0, (LPARAM)pszText);
if (lResult == -1)
SetNotPermitted();
}
LRESULT COleControl::OnSetText(WPARAM wParam, LPARAM lParam)
{
ASSERT(lParam == 0 || AfxIsValidString((LPCTSTR)lParam));
CString str = InternalGetText();
// Is the property changing?
if ((lParam == 0 && str.IsEmpty()) ||
(lParam != 0 && str == (LPCTSTR)lParam))
return 0;
DWORD dwStockPropMask = GetStockPropMask();
if (dwStockPropMask & STOCKPROP_CAPTION)
if (!BoundPropertyRequestEdit(DISPID_CAPTION))
return -1;
if (dwStockPropMask & STOCKPROP_TEXT)
if (!BoundPropertyRequestEdit(DISPID_TEXT))
return -1;
LRESULT lResult = 0;
m_strText = (LPCTSTR)lParam;
m_bModified = TRUE;
if (m_hWnd != NULL)
lResult = DefWindowProc(WM_SETTEXT, wParam, lParam);
OnTextChanged();
if (dwStockPropMask & STOCKPROP_CAPTION)
BoundPropertyChanged(DISPID_CAPTION);
if (dwStockPropMask & STOCKPROP_TEXT)
BoundPropertyChanged(DISPID_TEXT);
return lResult;
}
void COleControl::OnTextChanged()
{
// Can be overridden by subclass
InvalidateControl();
}
/////////////////////////////////////////////////////////////////////////////
// Enabled property
BOOL COleControl::GetEnabled()
{
return m_bEnabled;
}
void COleControl::SetEnabled(BOOL bEnabled)
{
// Is the property changing?
if (m_bEnabled == bEnabled)
return;
if (!BoundPropertyRequestEdit(DISPID_ENABLED))
SetNotPermitted();
m_bEnabled = bEnabled;
m_bModified = TRUE;
if (m_hWnd != NULL)
::EnableWindow(m_hWnd, m_bEnabled);
// If the control is UI Active and the Enabled property changed to FALSE,
// then UI Deactivate the control.
if (m_bUIActive && !bEnabled)
m_xOleInPlaceObject.UIDeactivate();
OnEnabledChanged();
BoundPropertyChanged(DISPID_ENABLED);
}
void COleControl::OnEnabledChanged()
{
// Can be overridden by subclass
InvalidateControl();
}
/////////////////////////////////////////////////////////////////////////////
// Font property
CFontHolder& COleControl::InternalGetFont()
{
return m_font;
}
LPFONTDISP COleControl::GetFont()
{
return m_font.GetFontDispatch();
}
void COleControl::SetFont(LPFONTDISP pFontDisp)
{
ASSERT((pFontDisp == NULL) ||
AfxIsValidAddress(pFontDisp, sizeof(IDispatch), FALSE));
m_font.InitializeFont(NULL, pFontDisp);
m_bModified = TRUE;
OnFontChanged();
BoundPropertyChanged(DISPID_FONT);
}
void COleControl::OnFontChanged()
{
// Can be overridden by subclass
// Send WM_SETFONT to control's window
if ((m_hWnd != NULL) &&
(GetStockPropMask() & STOCKPROP_FONT) &&
IsSubclassedControl())
{
HFONT hFontPrev = (HFONT)SendMessage(WM_GETFONT, 0, 0);
CFontHolder& font = InternalGetFont();
if (font.m_pFont != NULL)
{
HFONT hFont = font.GetFontHandle();
font.m_pFont->AddRefHfont(hFont);
SendMessage(WM_SETFONT, (WPARAM)hFont, 0);
if (m_hFontPrev != NULL)
{
ASSERT(hFontPrev == m_hFontPrev);
font.m_pFont->ReleaseHfont(hFontPrev);
}
m_hFontPrev = hFont;
}
else
{
SendMessage(WM_SETFONT, NULL, 0);
m_hFontPrev = NULL;
}
}
// Invalidate the control
InvalidateControl();
}
/////////////////////////////////////////////////////////////////////////////
// ForeColor property
OLE_COLOR COleControl::GetForeColor()
{
return m_clrForeColor;
}
void COleControl::SetForeColor(OLE_COLOR clrForeColor)
{
// Is the property changing?
if (m_clrForeColor == clrForeColor)
return;
if (FAILED(::OleTranslateColor(clrForeColor, NULL, NULL)))
ThrowError(CTL_E_INVALIDPROPERTYVALUE, AFX_IDP_E_INVALIDPROPERTYVALUE);
if (!BoundPropertyRequestEdit(DISPID_FORECOLOR))
SetNotPermitted();
m_clrForeColor = clrForeColor;
m_bModified = TRUE;
OnForeColorChanged();
BoundPropertyChanged(DISPID_FORECOLOR);
}
void COleControl::OnForeColorChanged()
{
// Can be overridden by subclass
InvalidateControl();
}
/////////////////////////////////////////////////////////////////////////////
// hWnd property
OLE_HANDLE COleControl::GetHwnd()
{
#ifdef _AFXDLL
return (OLE_HANDLE)((m_bInPlaceActive || m_bOpen) ? m_hWnd : NULL);
#else
return (OLE_HANDLE)(m_bInPlaceActive ? m_hWnd : NULL);
#endif
}
/////////////////////////////////////////////////////////////////////////////
// ReadyState property
long COleControl::GetReadyState()
{
return m_lReadyState;
}
////////////////////////////////////////////////////////////////////////////
// COleControl::XFontNotification
STDMETHODIMP_(ULONG) COleControl::XFontNotification::AddRef()
{
return 1;
}
STDMETHODIMP_(ULONG) COleControl::XFontNotification::Release()
{
return 0;
}
STDMETHODIMP COleControl::XFontNotification::QueryInterface(
REFIID iid, LPVOID* ppvObj)
{
ASSERT(ppvObj != NULL);
if (IsEqualIID(iid, IID_IUnknown) ||
IsEqualIID(iid, IID_IPropertyNotifySink))
{
*ppvObj = this;
return S_OK;
}
return E_NOINTERFACE;
}
STDMETHODIMP COleControl::XFontNotification::OnChanged(DISPID)
{
METHOD_PROLOGUE_EX(COleControl, FontNotification)
pThis->OnFontChanged();
pThis->m_bModified = TRUE;
pThis->BoundPropertyChanged(DISPID_FONT);
return S_OK;
}
STDMETHODIMP COleControl::XFontNotification::OnRequestEdit(DISPID)
{
return S_OK;
}
CFont* COleControl::SelectStockFont(CDC* pDC)
{
return SelectFontObject(pDC, m_font);
}
CFont* COleControl::SelectFontObject(CDC* pDC, CFontHolder& fontHolder)
{
return fontHolder.Select(pDC, m_rcBounds.Height(), m_cyExtent);
}
void COleControl::GetStockTextMetrics(LPTEXTMETRIC lptm)
{
m_font.QueryTextMetrics(lptm);
}
void COleControl::GetFontTextMetrics(LPTEXTMETRIC lptm, CFontHolder& fontHolder)
{
fontHolder.QueryTextMetrics(lptm);
}
/////////////////////////////////////////////////////////////////////////////
// Ambient property access
BOOL AFXAPI _GetI4Property(LPDISPATCH pDispatch, DISPID dwDispID, DWORD* pdwResult)
{
if (pDispatch == NULL)
return FALSE;
DISPPARAMS dispparams;
memset(&dispparams, 0, sizeof dispparams);
VARIANT vaResult;
AfxVariantInit(&vaResult);
EXCEPINFO excepInfo;
memset(&excepInfo, 0, sizeof excepInfo);
UINT nArgErr = (UINT)-1; // initialize to invalid arg
HRESULT hr = pDispatch->Invoke(dwDispID, IID_NULL, 0, DISPATCH_PROPERTYGET,
&dispparams, &vaResult, &excepInfo, &nArgErr);
if (SUCCEEDED(hr))
{
if ((V_VT(&vaResult) == VT_I4) ||
SUCCEEDED(VariantChangeType(&vaResult, &vaResult, 0, VT_I4)))
{
*pdwResult = V_I4(&vaResult);
return TRUE;
}
}
VariantClear(&vaResult);
if (excepInfo.bstrSource != NULL)
SysFreeString(excepInfo.bstrSource);
if (excepInfo.bstrDescription != NULL)
SysFreeString(excepInfo.bstrDescription);
if (excepInfo.bstrHelpFile != NULL)
SysFreeString(excepInfo.bstrHelpFile);
return FALSE;
}
COleDispatchDriver* COleControl::GetAmbientDispatchDriver()
{
if (m_ambientDispDriver.m_lpDispatch == NULL)
{
// Initialize pointer to ambient property dispinterface.
IDispatch* pDispatch = NULL;
if (m_pClientSite != NULL &&
SUCCEEDED(m_pClientSite->QueryInterface(IID_IDispatch,
reinterpret_cast<void**>(&pDispatch))))
{
ASSERT(pDispatch != NULL);
m_ambientDispDriver.AttachDispatch(pDispatch);
}
}
return &m_ambientDispDriver;
}
AFX_STATIC_DATA const DWORD _afxAmbientFlags[] =
{
QACONTAINER_MESSAGEREFLECT, // -706
0, // -707
0, // -708
QACONTAINER_USERMODE, // -709
QACONTAINER_UIDEAD, // -710
QACONTAINER_SHOWGRABHANDLES, // -711
QACONTAINER_SHOWHATCHING, // -712
QACONTAINER_DISPLAYASDEFAULT, // -713
QACONTAINER_SUPPORTSMNEMONICS, // -714
QACONTAINER_AUTOCLIP, // -715
};
BOOL COleControl::GetAmbientProperty(DISPID dwDispID, VARTYPE vtProp, void* pvProp)
{
// First, check whether ambient property can be obtained from cache.
_AFXCTL_AMBIENT_CACHE* pAmbientCache = _afxAmbientCache;
if (pAmbientCache->m_bValid)
{
switch (vtProp)
{
// Fetch boolean by selecting appropriate flag in cache.
case VT_BOOL:
{
int nIndex = DISPID_AMBIENT_MESSAGEREFLECT - dwDispID;
DWORD dwFlag;
if (nIndex >= 0 && nIndex < _countof(_afxAmbientFlags) &&
(dwFlag = _afxAmbientFlags[nIndex]) != 0)
{
*(BOOL*)pvProp =
((pAmbientCache->m_dwAmbientFlags & dwFlag) != 0);
return TRUE;
}
}
break;
// Fetch color, appearance, or font from corresponding cache entry.
case VT_I4:
switch (dwDispID)
{
case DISPID_AMBIENT_FORECOLOR:
*(DWORD*)pvProp = pAmbientCache->m_colorFore;
return TRUE;
case DISPID_AMBIENT_BACKCOLOR:
*(DWORD*)pvProp = pAmbientCache->m_colorBack;
return TRUE;
case DISPID_AMBIENT_APPEARANCE:
*(DWORD*)pvProp = pAmbientCache->m_dwAppearance;
return TRUE;
}
break;
case VT_I2:
if (dwDispID == DISPID_AMBIENT_APPEARANCE)
{
*(short*)pvProp = (short)pAmbientCache->m_dwAppearance;
return TRUE;
}
break;
case VT_DISPATCH:
if ((dwDispID == DISPID_AMBIENT_FONT) &&
(pAmbientCache->m_pFont != NULL) &&
SUCCEEDED(pAmbientCache->m_pFont->QueryInterface(IID_IFontDisp,
reinterpret_cast<void**>(pvProp))))
{
return TRUE;
}
break;
}
}
// If there's no ambient dispatch interface available, then fail.
COleDispatchDriver* pDispDriver = GetAmbientDispatchDriver();
if (pDispDriver->m_lpDispatch == NULL)
return FALSE;
// If requested property is of type VT_I4, use optimized function.
if (vtProp == VT_I4)
return _GetI4Property(pDispDriver->m_lpDispatch, dwDispID,
(DWORD*)pvProp);
// If none of the above apply, just use the dispatch driver.
BOOL bSuccess = FALSE;
TRY
{
pDispDriver->GetProperty(dwDispID, vtProp, pvProp);
bSuccess = TRUE;
}
END_TRY
return bSuccess;
}
short COleControl::AmbientAppearance()
{
DWORD dwAppearance;
if (!GetAmbientProperty(DISPID_AMBIENT_APPEARANCE, VT_I4, &dwAppearance))
dwAppearance = 0;
return (short)dwAppearance;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -