📄 atlcontrolwin.cpp
字号:
// ATLControlWin.cpp : Implementation of CATLControlWin
#include "stdafx.h"
#include "ATLControl.h"
#include "ATLControlWin.h"
/////////////////////////////////////////////////////////////////////////////
// CATLControlWin
STDMETHODIMP CATLControlWin::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_IATLControlWin,
};
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
HRESULT CATLControlWin::OnDraw(ATL_DRAWINFO & di)
{
// ****** 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(di.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(di.hdcDraw, clrTextBackgroundColor);
COLORREF clrOldForegroundColor = ::SetTextColor(di.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 = (HBRUSH)::SelectObject(di.hdcDraw, hBrush);
// draw the background
::Rectangle(di.hdcDraw, di.prcBounds->left, di.prcBounds->top, di.prcBounds->right, di.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(di.hdcDraw, m_lptstrCaption, cx, cy);
switch(m_lAlignment)
{
case EALIGN_CENTER:
iHor = (di.prcBounds->right - cx) / 2;
iVer = di.prcBounds->top + 3;
break;
case EALIGN_RIGHT:
iHor = di.prcBounds->right - cx - 3;
iVer = di.prcBounds->top + 3;
break;
// case EALIGN_LEFT:
default:
iHor = di.prcBounds->left + 3;
iVer = di.prcBounds->top + 3;
break;
}
// output our text
::ExtTextOut(di.hdcDraw, iHor, iVer, ETO_CLIPPED | ETO_OPAQUE, (LPCRECT) di.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(di.hdcDraw, clrEdgeBackgroundColor);
::SetTextColor(di.hdcDraw, clrEdgeForegroundColor);
// draw the 3D edge
::DrawEdge(di.hdcDraw, (LPRECT)(LPCRECT) di.prcBounds, uiBorderStyle, uiBorderFlags);
// **
// ****** Draw the border ******
// ****** Reset the colors ******
// **
// restore the original colors
::SetBkColor(di.hdcDraw, clrOldBackgroundColor);
::SetTextColor(di.hdcDraw, clrOldForegroundColor);
// **
// ****** Reset the colors ******
// ****** release the text font ******
// **
if(hOldFont)
// select the old object
::SelectObject(di.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(!di.bOptimize)
{
// select the old brush back
::SelectObject(di.hdcDraw, hOldBrush);
// destroy the brush we created
::DeleteObject(hBrush);
// clear the brush handles
hBrush = hOldBrush = NULL;
}
return S_OK;
}
STDMETHODIMP CATLControlWin::CaptionMethod(BSTR bstrCaption, VARIANT varAlignment, long * lRetVal)
{
// needed for the W2A macro
USES_CONVERSION;
HRESULT hResult = S_OK;
// return value initialized to failure result
*lRetVal = FALSE;
// convert the string to ANSI
LPTSTR lptstrTempCaption = W2A(bstrCaption);
// if the variant is a long just use the value
if(VT_I4 == varAlignment.vt)
{
// assign the value to our member variable
m_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_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_lAlignment = EALIGN_CENTER;
break;
case EALIGN_RIGHT:
m_lAlignment = EALIGN_RIGHT;
break;
default:
m_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(lptstrTempCaption != 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(lptstrTempCaption) + 1];
// assign the string to our member variable
lstrcpy(m_lptstrCaption, lptstrTempCaption);
}
// did they pass us bad data?
if(m_lAlignment < EALIGN_LEFT || m_lAlignment > EALIGN_RIGHT)
// sure did, lets fix their little red wagon
m_lAlignment = EALIGN_LEFT;
// fire the global change event
this->FireChange();
// force the control to repaint itself
this->FireViewChange();
// this->InvalidateControl(); <== MFC Version
}
// return the result of the function call
return hResult;
}
STDMETHODIMP CATLControlWin::get_Alignment(long * pVal)
{
HRESULT hResult = S_OK;
// return our current setting
*pVal = m_lAlignment;
return hResult;
}
STDMETHODIMP CATLControlWin::put_Alignment(long newVal)
{
HRESULT hResult = S_OK;
// if we are in the valid range for the property
if(newVal >= EALIGN_LEFT && newVal <= EALIGN_RIGHT)
{
// set the new property value
m_lAlignment = newVal;
// let the control know that the property has changed
this->SetDirty(TRUE);
// this->SetModifiedFlag(); <== MFC version
// fire the global change event
this->FireChange();
// refresh the property browser
this->FireOnChanged(dispidAlignment);
// this->BoundPropertyChanged(dispidAlignment); <== MFC Version
// force the control to repaint itself
this->FireViewChange();
// this->InvalidateControl(); <== MFC Version
}
return hResult;
}
STDMETHODIMP CATLControlWin::get_CaptionProp(VARIANT varAlignment, BSTR * pVal)
{
// needed for the T2OLE macro
USES_CONVERSION;
// if there is a string
if(*pVal)
{
// free the string because we are going to replace it
::SysFreeString(*pVal);
// clear the reference just to be safe
*pVal = NULL;
}
// convert the ANSI string to an OLECHAR and then allocate a BSTR
*pVal = ::SysAllocString(T2OLE(m_lptstrCaption));
return S_OK;
}
STDMETHODIMP CATLControlWin::put_CaptionProp(VARIANT varAlignment, BSTR newVal)
{
long lRetVal;
// defer to the CaptionMethod implementation
HRESULT hResult = this->CaptionMethod(newVal, varAlignment, &lRetVal);
// if the function returned success
if(TRUE == lRetVal)
// let the control know that the property has changed
this->SetDirty(TRUE);
// this->SetModifiedFlag(); <== MFC version
// return the result
return hResult;
}
STDMETHODIMP CATLControlWin::get_BackColor(OLE_COLOR * pVal)
{
// return the color
*pVal = m_BackColor;
return S_OK;
}
STDMETHODIMP CATLControlWin::put_BackColor(OLE_COLOR newVal)
{
// if the value is the same
if(newVal == m_BackColor)
return S_OK;
// store the value
m_BackColor = newVal;
// let the container know that the value has changed
this->FireOnChanged(DISPID_BACKCOLOR);
// this->AmbientPropertyChanged(DISPID_BACKCOLOR); <== MFC Version
// redraw the control
this->FireViewChange();
// this->InvalidateControl(); <== MFC Version
// set the dirty flag
this->SetDirty(TRUE);
// this->SetModifiedFlag(); <== MFC Version
// exit
return S_OK;
}
void CATLControlWin::FireChange(void)
{
// needed for the W2A macro
USES_CONVERSION;
// get a BSTR that can be passed via the event
BSTR bstrCaption = ::SysAllocString(T2OLE(m_lptstrCaption));
// fire the change event
this->Fire_Change(&bstrCaption, &m_lAlignment);
// convert the string to ANSI
LPTSTR lptstrTempCaption = W2A(bstrCaption);
// free the data that was passed back
::SysFreeString(bstrCaption);
// 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(lptstrTempCaption) + 1];
// assign the string to our member variable
lstrcpy(m_lptstrCaption, lptstrTempCaption);
}
LRESULT CATLControlWin::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled)
{
// if we have a window handle
if(m_hWnd)
// revoke the control as a drag and drop target
::RevokeDragDrop(m_hWnd);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -