📄 bcfcontrolctl.cpp
字号:
//
STDMETHODIMP CBCFControlControl::SaveTextState
(
IPropertyBag *pPropertyBag,
BOOL fWriteDefaults
)
{
HRESULT hr = S_OK;
VARIANT v;
if(lstrlen(m_lptstrCaption) || fWriteDefaults)
{
::VariantInit(&v);
v.vt = VT_BSTR;
v.bstrVal = ::SysAllocString(OLESTRFROMANSI(m_lptstrCaption));
if (!v.bstrVal) return E_OUTOFMEMORY;
hr = pPropertyBag->Write(OLESTRFROMANSI("Caption"), &v);
::SysFreeString(v.bstrVal);
RETURN_ON_FAILURE(hr);
}
if(m_DefaultState.lAlignment != m_state.lAlignment || fWriteDefaults)
{
::VariantInit(&v);
v.vt = VT_I4;
v.lVal = m_state.lAlignment;
hr = pPropertyBag->Write(OLESTRFROMANSI("Alignment"), &v);
RETURN_ON_FAILURE(hr);
}
if(m_DefaultState.ocBackColor != m_state.ocBackColor || fWriteDefaults)
{
::VariantInit(&v);
v.vt = VT_I4;
v.lVal = m_state.ocBackColor;
hr = pPropertyBag->Write(OLESTRFROMANSI("BackColor"), &v);
RETURN_ON_FAILURE(hr);
}
if(lstrlen(m_lptstrTextDataPath) || fWriteDefaults)
{
::VariantInit(&v);
v.vt = VT_BSTR;
v.bstrVal = ::SysAllocString(OLESTRFROMANSI(m_lptstrTextDataPath));
if (!v.bstrVal) return E_OUTOFMEMORY;
hr = pPropertyBag->Write(OLESTRFROMANSI("TextDataPath"), &v);
::SysFreeString(v.bstrVal);
RETURN_ON_FAILURE(hr);
}
return hr;
}
//=--------------------------------------------------------------------------=
// CBCFControlControl::SaveBinaryState
//=--------------------------------------------------------------------------=
// save out the binary state for this control, using the given IStream object.
//
// Parameters:
// IStream * - [in] save to which you should save.
//
// Output:
// HRESULT
//
// Notes:
// - it is important that you seek to the end of where you saved your
// properties when you're done with the IStream.
//
STDMETHODIMP CBCFControlControl::SaveBinaryState
(
IStream *pStream
)
{
HRESULT hr = S_OK;
// store the length of the string and the NULL
m_state.lCaptionLength = lstrlen(m_lptstrCaption) + 1;
// store the length of the string and the NULL
m_state.lTextDataPathLength = lstrlen(m_lptstrTextDataPath) + 1;
// write the state of the data to the stream
hr = pStream->Write(&m_state, sizeof(m_state), NULL);
RETURN_ON_FAILURE(hr);
// write the string and the NULL
hr = pStream->Write(m_lptstrTextDataPath, m_state.lCaptionLength, NULL);
RETURN_ON_FAILURE(hr);
// write the string and the NULL
hr = pStream->Write(m_lptstrCaption, m_state.lTextDataPathLength, NULL);
RETURN_ON_FAILURE(hr);
return S_OK;
}
//=--------------------------------------------------------------------------=
// CBCFControlControl::OnDraw
//=--------------------------------------------------------------------------=
// "I don't very much enjoy looking at paintings in general. i know too
// much about them. i take them apart."
// - georgia o'keeffe (1887-1986)
//
// Parameters:
// DWORD - [in] drawing aspect
// HDC - [in] HDC to draw to
// LPCRECTL - [in] rect we're drawing to
// LPCRECTL - [in] window extent and origin for meta-files
// HDC - [in] HIC for target device
// BOOL - [in] can we optimize dc handling?
//
// Output:
// HRESULT
//
// Notes:
//
HRESULT CBCFControlControl::OnDraw
(
DWORD dvAspect,
HDC hdcDraw,
LPCRECTL prcBounds,
LPCRECTL prcWBounds,
HDC hicTargetDevice,
BOOL fOptimize
)
{
// ****** Get the text font ******
// **
HFONT hFont = NULL, hOldFont = NULL;
// if there isn't a font object
if(!m_pFont)
// try to load one
this->LoadFont();
if(m_pFont)
{
// get a font handle
m_pFont->get_hFont(&hFont);
// increment the ref count so the font doesn't drop
// out from under us
m_pFont->AddRefHfont(hFont);
::SelectObject(hdcDraw, hFont);
}
// **
// ****** Get the text font ******
// ****** Get the colors ******
// **
// use the window color as the background color
OLE_COLOR tColor;
this->get_BackColor(&tColor);
COLORREF clrTextBackgroundColor = this->TranslateColor(tColor);
// then use the normal windows color for the text
COLORREF clrTextForegroundColor = this->TranslateColor(::GetSysColor(COLOR_WINDOWTEXT));
// set to the system color
COLORREF clrEdgeBackgroundColor = ::GetSysColor(COLOR_3DFACE);
COLORREF clrEdgeForegroundColor = ::GetSysColor(COLOR_3DFACE);
// **
// ****** Get the colors ******
// ****** Draw the background ******
// **
// set the text color
COLORREF clrOldBackgroundColor = ::SetBkColor(hdcDraw, clrTextBackgroundColor);
COLORREF clrOldForegroundColor = ::SetTextColor(hdcDraw, clrTextForegroundColor);
// if we don't have a brush
if(hBrush == NULL)
// create a solid brush
hBrush = ::CreateSolidBrush(clrTextBackgroundColor);
// select the brush and save the old one
hOldBrush = ::SelectObject(hdcDraw, hBrush);
// draw the background
::Rectangle(hdcDraw, prcBounds->left, prcBounds->top, prcBounds->right, prcBounds->bottom);
// **
// ****** Draw the background ******
// ****** Draw the text ******
// **
int iHor, iVer;
// get the size of the text for this DC
int cx = 0, cy = 0;
this->GetTextExtent(hdcDraw, m_lptstrCaption, cx, cy);
switch(m_state.lAlignment)
{
case EALIGN_CENTER:
iHor = (prcBounds->right - cx) / 2;
iVer = prcBounds->top + 3;
break;
case EALIGN_RIGHT:
iHor = prcBounds->right - cx - 3;
iVer = prcBounds->top + 3;
break;
// case EALIGN_LEFT:
default:
iHor = prcBounds->left + 3;
iVer = prcBounds->top + 3;
break;
}
// output our text
::ExtTextOut(hdcDraw, iHor, iVer, ETO_CLIPPED | ETO_OPAQUE, (LPCRECT) prcBounds, m_lptstrCaption, lstrlen(m_lptstrCaption), NULL);
// **
// ****** Draw the text ******
// ****** Draw the border ******
// **
// set the edge style and flags
UINT uiBorderStyle = EDGE_SUNKEN;
UINT uiBorderFlags = BF_RECT;
// set the edge color
::SetBkColor(hdcDraw, clrEdgeBackgroundColor);
::SetTextColor(hdcDraw, clrEdgeForegroundColor);
// draw the 3D edge
::DrawEdge(hdcDraw, (LPRECT)(LPCRECT) prcBounds, uiBorderStyle, uiBorderFlags);
// **
// ****** Draw the border ******
// ****** Reset the colors ******
// **
// restore the original colors
::SetBkColor(hdcDraw, clrOldBackgroundColor);
::SetTextColor(hdcDraw, clrOldForegroundColor);
// **
// ****** Reset the colors ******
// ****** release the text font ******
// **
if(hOldFont)
// select the old object
::SelectObject(hdcDraw, hOldFont);
// increment the ref count so the font doesn't drop
// out from under us
if(m_pFont && hFont)
m_pFont->ReleaseHfont(hFont);
// **
// ****** Get the text font ******
// The container does not support optimized drawing.
if(!fOptimize)
{
// select the old brush back
::SelectObject(hdcDraw, hOldBrush);
// destroy the brush we created
::DeleteObject(hBrush);
// clear the brush handles
hBrush = hOldBrush = NULL;
}
return S_OK;
}
//=--------------------------------------------------------------------------=
// CBCFControlControl::WindowProc
//=--------------------------------------------------------------------------=
// window procedure for this control. nothing terribly exciting.
//
// Parameters:
// see win32sdk on window procs [sans HWND -- it's in m_hwnd if you have one]
//
// Notes:
//
LRESULT CBCFControlControl::WindowProc(UINT msg, WPARAM wParam, LPARAM lParam)
{
LRESULT lRetVal = FALSE;
switch(msg)
{
case WM_KEYDOWN:
this->OnKeyDown(wParam, LOWORD(lParam), HIWORD(lParam));
break;
case WM_LBUTTONDOWN:
this->OnLButtonDown(wParam, (short) LOWORD(lParam), (short) HIWORD(lParam));
this->OcxDefWindowProc(msg, wParam, lParam);
break;
default:
lRetVal = this->OcxDefWindowProc(msg, wParam, lParam);
break;
}
return lRetVal;
}
//=--------------------------------------------------------------------------=
// CBCFControlControl::AboutBox
//=--------------------------------------------------------------------------=
// prints up an about box. fweeeee.
//
// Notes:
//
void CBCFControlControl::AboutBox
(
void
)
{
// TODO: Ideally, one would use DialogBox, and some sort of Dialog Box here if
// they wanted a slightly more interesting About Box ... you should
// still call ModalDialog first, however.
//
ModalDialog(TRUE);
MessageBox(NULL, "This is My Control", "About BCFControl", MB_OK | MB_TASKMODAL);
ModalDialog(FALSE);
}
STDMETHODIMP CBCFControlControl::CaptionMethod(BSTR bstrCaption, VARIANT varAlignment, long FAR * lRetVal)
{
HRESULT hResult = S_OK;
// return value initialized to failure result
*lRetVal = FALSE;
MAKE_ANSIPTR_FROMWIDE(lpctstrCaption, bstrCaption);
// if the variant is a long just use the value
if(VT_I4 == varAlignment.vt)
{
// assign the value to our member variable
m_state.lAlignment = varAlignment.lVal;
// set the return value
*lRetVal = TRUE;
}
// if the user didn't supply an alignment parameter we will assign the default
else if(VT_ERROR == varAlignment.vt || VT_EMPTY == varAlignment.vt)
{
// assign the value to our member variable
m_state.lAlignment = EALIGN_LEFT;
// set the return value
*lRetVal = TRUE;
}
else
{
// get a variant that we can use for conversion purposes
VARIANT varConvertedValue;
// initialize the variant
::VariantInit(&varConvertedValue);
// see if we can convert the data type to something useful - VariantChangeTypeEx() could also be used
if(S_OK == ::VariantChangeType(&varConvertedValue, (VARIANT *) &varAlignment, 0, VT_I4))
{
// assign the value to our member variable
switch(varConvertedValue.lVal)
{
case EALIGN_CENTER:
m_state.lAlignment = EALIGN_CENTER;
break;
case EALIGN_RIGHT:
m_state.lAlignment = EALIGN_RIGHT;
break;
default:
m_state.lAlignment = EALIGN_LEFT;
break;
}
// set the return value
*lRetVal = TRUE;
}
else
{
// at this point we could either throw an error indicating there was a problem converting
// the data or change the return type of the method and return the HRESULT value from the
// the "VariantChangeType" call.
}
}
// if everything was OK
if(TRUE == *lRetVal)
{
// if we have a string
if(lpctstrCaption != NULL)
{
// if we have a string
if(m_lptstrCaption)
{
// delete the existing string
delete [] m_lptstrCaption;
// clear the reference just to be safe
m_lptstrCaption = NULL;
}
// allocate a new string
m_lptstrCaption = new TCHAR[lstrlen(lpctstrCaption) + 1];
// assign the string to our member variable
lstrcpy(m_lptstrCaption, lpctstrCaption);
}
// fire the change event
this->FireChange();
// did they pass us bad data?
if(m_state.lAlignment < EALIGN_LEFT || m_state.lAlignment > EALIGN_RIGHT)
// sure did, lets fix their little red wagon
m_state.lAlignment = EALIGN_LEFT;
// force the control to repaint itself
this->InvalidateControl(NULL);
}
// return the result of the function call
return hResult;
}
STDMETHODIMP CBCFControlControl::get_Alignment(long FAR* Value)
{
HRESULT hResult = S_OK;
// return our current setting
*Value = m_state.lAlignment;
return hResult;
}
STDMETHODIMP CBCFControlControl::put_Alignment(long Value)
{
HRESULT hResult = S_OK;
// if we are in the valid range for the property
if(Value >= EALIGN_LEFT && Value <= EALIGN_RIGHT)
{
// set the new property value
m_state.lAlignment = Value;
// fire the change event
this->FireChange();
// let the control know that the property has changed
m_fDirty = TRUE;
// this->SetModifiedFlag(); <== MFC version
// refresh the property browser
this->PropertyChanged(dispidAlignment);
// this->BoundPropertyChanged(dispidAlignment); <== MFC Version
}
return hResult;
}
STDMETHODIMP CBCFControlControl::get_CaptionProp(VARIANT varAlignment, BSTR FAR* bstrRetVal)
{
// if there is a string
if(*bstrRetVal);
{
// free the string because we are going to replace it
::SysFreeString(*bstrRetVal);
// clear the reference just to be safe
*bstrRetVal = NULL;
}
// return the caption as a BSTR
*bstrRetVal = ::SysAllocString(OLESTRFROMANSI(m_lptstrCaption));
return S_OK;
}
STDMETHODIMP CBCFControlControl::put_CaptionProp(VARIANT varAlignment, BSTR lpszNewValue)
{
long lRetVal;
HRESULT hResult = this->CaptionMethod(lpszNewValue, varAlignment, &lRetVal);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -