📄 bcfcontrolctl.cpp
字号:
// use the "CaptionMethod" implementation
if(hResult == S_OK && lRetVal)
// let the container know that the property has changed
m_fDirty = TRUE;
// this->SetModifiedFlag(); <== MFC version
return hResult;
}
STDMETHODIMP CBCFControlControl::get_BackColor(OLE_COLOR * Value)
{
// make sure that we have a good pointer
CHECK_POINTER(Value);
// set the return value
*Value = m_state.ocBackColor;
// return the result
return S_OK;
}
STDMETHODIMP CBCFControlControl::put_BackColor(OLE_COLOR Value)
{
// if the value is the same
if (m_state.ocBackColor == Value)
// exit
return S_OK;
// save the value
m_state.ocBackColor = Value;
// let the container know that the value has changed
this->PropertyChanged(DISPID_BACKCOLOR);
// this->AmbientPropertyChanged(DISPID_BACKCOLOR); <== MFC Version
// redraw the control
this->InvalidateControl(NULL);
// this->InvalidateControl(); <== MFC Version
// set the dirty flag
m_fDirty = TRUE;
// this->SetModifiedFlag(); <== MFC Version
// exit
return S_OK;
}
STDMETHODIMP CBCFControlControl::get_ReadyState(long * Value)
{
// make sure that we have a good pointer
CHECK_POINTER(Value);
// set the return value
*Value = m_state.lReadyState;
// return the result
return S_OK;
}
STDMETHODIMP CBCFControlControl::get_TextDataPath(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_lptstrTextDataPath));
return S_OK;
}
STDMETHODIMP CBCFControlControl::put_TextDataPath(BSTR bstrNewValue)
{
HRESULT hResult = S_OK;
// get a ANSI string from the BSTR
MAKE_ANSIPTR_FROMWIDE(lpctstrTextDataPath, bstrNewValue);
// if we have a string
if(lpctstrTextDataPath != NULL)
{
// if we have a string
if(m_lptstrTextDataPath)
{
// delete the existing string
delete [] m_lptstrTextDataPath;
// clear the reference just to be safe
m_lptstrTextDataPath = NULL;
}
// allocate a new string
m_lptstrTextDataPath = new TCHAR[lstrlen(lpctstrTextDataPath) + 1];
// assign the string to our member variable
lstrcpy(m_lptstrTextDataPath, lpctstrTextDataPath);
}
// start the asynchronous download of the data
this->SetupDownload(OLESTRFROMANSI(m_lptstrTextDataPath), dispidTextDataPath);
// let the container know that the property has changed
m_fDirty = TRUE;
// this->SetModifiedFlag(); <== MFC version
return hResult;
}
HRESULT CBCFControlControl::OnData(DISPID propId, DWORD bscfFlag, IStream * strm, DWORD dwSize)
{
HRESULT hr = NOERROR;
// if this is the first notification
if(bscfFlag & BSCF_FIRSTDATANOTIFICATION)
{
// if we have a reference
if(m_lptstrCaption)
{
// delete the string buffer
delete [] m_lptstrCaption;
// clear the reference just to be safe
m_lptstrCaption = NULL;
}
}
// alloc a temp buffer
LPTSTR lptstrTempBuffer = new TCHAR[dwSize + 1];
ULONG ulBytesRead;
// read the data to a temp buffer
hr = strm->Read(lptstrTempBuffer, dwSize, &ulBytesRead);
// if we read in any data
if(hr == S_OK && ulBytesRead)
{
// nul terminate the amount of data the was actually read in
lptstrTempBuffer[ulBytesRead] = '\0';
// get a new buffer with enough space to hold all of the data
LPTSTR lptstrNewBuffer = new TCHAR[lstrlen(m_lptstrCaption) + ulBytesRead + 1];
// copy the existing data to the new buffer
lstrcpy(lptstrNewBuffer, m_lptstrCaption);
// add the new data to the buffer
lstrcat(lptstrNewBuffer, lptstrTempBuffer);
// remove the existing string
delete [] m_lptstrCaption;
// copy the data to the buffer
m_lptstrCaption = lptstrNewBuffer;
// set the dirty flag
m_fDirty = TRUE;
// redraw the control
this->InvalidateControl(NULL);
}
// if this is our last notification
if(bscfFlag & BSCF_LASTDATANOTIFICATION)
{
// set the ready state of the control
m_state.lReadyState = READYSTATE_COMPLETE;
// set the dirty flag
m_fDirty = TRUE;
}
// return the result
return(hr);
}
STDMETHODIMP CBCFControlControl::MapPropertyToPage(DISPID, LPCLSID)
{
return E_NOTIMPL;
}
STDMETHODIMP CBCFControlControl::GetPredefinedStrings(DISPID dispid, CALPOLESTR * lpcaStringsOut, CADWORD * lpcaCookiesOut)
{
HRESULT hResult = S_FALSE;
// we should have gotten two pointers if we didn't
if((lpcaStringsOut == NULL) || (lpcaCookiesOut == NULL))
// we are out of here
return E_POINTER;
// if this is the property that we are looking for
if(dispid == dispidAlignment)
{
ULONG ulElems = 3;
// allocate the memory for our string array
lpcaStringsOut->pElems = (LPOLESTR *) ::CoTaskMemAlloc(sizeof(LPOLESTR) * ulElems);
// if we couldn't allocate the memory
if(lpcaStringsOut->pElems == NULL)
// were out of here
return E_OUTOFMEMORY;
// allocate the memory for our cookie array
lpcaCookiesOut->pElems = (DWORD*) ::CoTaskMemAlloc(sizeof(DWORD*) * ulElems);
// if we couldn't allocate the memory
if (lpcaCookiesOut->pElems == NULL)
{
// free the string array
::CoTaskMemFree(lpcaStringsOut->pElems);
// exit the function
return E_OUTOFMEMORY;
}
// store the number of elements in each array
lpcaStringsOut->cElems = ulElems;
lpcaCookiesOut->cElems = ulElems;
// allocate the strings
lpcaStringsOut->pElems[0] = OLESTRFROMANSI(EALIGN_LEFT_TEXT);
lpcaStringsOut->pElems[1] = OLESTRFROMANSI(EALIGN_CENTER_TEXT);
lpcaStringsOut->pElems[2] = OLESTRFROMANSI(EALIGN_RIGHT_TEXT);
// assign the cookie value
lpcaCookiesOut->pElems[0] = EALIGN_LEFT;
lpcaCookiesOut->pElems[1] = EALIGN_CENTER;
lpcaCookiesOut->pElems[2] = EALIGN_RIGHT;
hResult = S_OK;
}
return hResult;
}
STDMETHODIMP CBCFControlControl::GetPredefinedValue(DISPID dispid, DWORD dwCookie, VARIANT* lpvarOut)
{
BOOL bResult = FALSE;
// which property is it
switch(dispid)
{
case dispidAlignment:
// clear the variant
::VariantInit(lpvarOut);
// set the type to a long
lpvarOut->vt = VT_I4;
// set the value to the value that was stored with the string
lpvarOut->lVal = dwCookie;
// set the return value
bResult = TRUE;
break;
}
return bResult;
}
STDMETHODIMP CBCFControlControl::GetDisplayString(DISPID dispid, BSTR* lpbstr)
{
HRESULT hResult = S_FALSE;
// which property is it
switch(dispid)
{
case dispidAlignment:
{
switch(m_state.lAlignment)
{
case EALIGN_LEFT:
*lpbstr = BSTRFROMANSI(EALIGN_LEFT_TEXT);
break;
case EALIGN_CENTER:
*lpbstr = BSTRFROMANSI(EALIGN_CENTER_TEXT);
break;
case EALIGN_RIGHT:
*lpbstr = BSTRFROMANSI(EALIGN_RIGHT_TEXT);
break;
}
// set the return value
hResult = S_OK;
}
break;
}
return hResult;
}
void CBCFControlControl::FireChange(void)
{
// get a BSTR that can be passed via the event
BSTR bstrCaption = ::SysAllocString(OLESTRFROMANSI(m_lptstrCaption));
// fire the change event
this->FireEvent(&(m_rgBCFControlEvents[BCFControlEvent_Change]), &bstrCaption, &m_state.lAlignment);
// create an ANSI string
MAKE_ANSIPTR_FROMWIDE(lpctstrCaption, 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(lpctstrCaption) + 1];
// assign the string to our member variable
lstrcpy(m_lptstrCaption, lpctstrCaption);
}
static FONTDESC _fdDefault =
{
sizeof(FONTDESC),
L"MS Sans Serif",
FONTSIZE(8),
FW_NORMAL,
DEFAULT_CHARSET,
FALSE,
FALSE,
FALSE
};
void CBCFControlControl::LoadFont(void)
{
// if there isn't a font object
if(!m_pFont)
// get the font from the container
this->GetAmbientFont(&m_pFont);
// if there still isn't a font object
if(!m_pFont)
// create a default font object
::OleCreateFontIndirect(&_fdDefault, IID_IFont, (void **) &m_pFont);
}
void CBCFControlControl::GetTextExtent(HDC hDC, LPCTSTR lpctstrString, int & cx, int & cy)
{
// if we haven't gotten the dimensions yet
if(!bRetrievedDimensions)
{
// get all of the widths for all of the chars
::GetCharWidth(hDC, 0, 255, &iCharWidthArray[0]);
// get the spacing between the chars
iCharacterSpacing = ::GetTextCharacterExtra(hDC);
// make sure that this only executes once
bRetrievedDimensions = TRUE;
// get the metrics of this DC
TEXTMETRIC tmMetrics;
::GetTextMetrics(hDC, &tmMetrics);
// get the height
iCharacterHeight = tmMetrics.tmHeight;
}
// return the height
cy = iCharacterHeight;
// set the initial value to 0
int iTextWidth = 0;
// get the number of characters in our string
long lTextLength = lstrlen(lpctstrString);
// if we have a character
if(lTextLength)
{
long lEndCharPos = lTextLength - 1;
// add up the widths of the characters and the spacing
for(long lCount = 0; lCount <= lEndCharPos; lCount++)
iTextWidth += (iCharWidthArray[(BYTE)(lpctstrString[lCount])] + iCharacterSpacing);
}
// return the width
cx = iTextWidth;
}
void CBCFControlControl::CopyDataToClipboard(void)
{
BOOL bHaveClipboard = TRUE;
// if we don't have an IDataObject on the clipboard?
if(::OleIsCurrentClipboard((IDataObject *) this) != S_OK)
// set the flag
bHaveClipboard = FALSE;
// put data in the storage
this->PrepareDataForTransfer();
// if we don't have the clipboard
if(!bHaveClipboard)
{
// clear the clipboard
::OleFlushClipboard();
// put the data on the clipboard
::OleSetClipboard((IDataObject *) this);
}
}
void CBCFControlControl::PrepareDataForTransfer(void)
{
// get the length of the data to copy
long lLength = lstrlen(m_lptstrCaption) + 1;
// create a global memory object
HGLOBAL hGlobal = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(TCHAR) * lLength);
// lock the memory down
LPTSTR lpTempBuffer = (LPTSTR) ::GlobalLock(hGlobal);
// copy the string
for(long lCount = 0; lCount < lLength - 1; lCount++)
lpTempBuffer[lCount] = m_lptstrCaption[lCount];
// null terminate the string
lpTempBuffer[lCount] = '\0';
// unlock the memory
::GlobalUnlock(hGlobal);
// copy all of the members
sTextFormatEtc.cfFormat = CF_TEXT;
sTextFormatEtc.ptd = NULL;
sTextFormatEtc.dwAspect = 0;
sTextFormatEtc.lindex = -1;
sTextFormatEtc.tymed = TYMED_HGLOBAL;
// if we have already allocated the data
if(sTextStgMedium.hGlobal)
// release it
::ReleaseStgMedium(&sTextStgMedium);
sTextStgMedium.tymed = TYMED_HGLOBAL;
sTextStgMedium.hGlobal = hGlobal;
sTextStgMedium.pUnkForRelease = NULL;
// if we have custom clipboard format support
if(m_uiCustomFormat)
{
// create a global memory object
HGLOBAL hGlobal = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(m_state.lAlignment));
// lock the memory down
LONG * lpTempBuffer = (LONG *) ::GlobalLock(hGlobal);
// set our data buffer
*lpTempBuffer = m_state.lAlignment;
// unlock the memory
::GlobalUnlock(hGlobal);
// copy all of the members
sCustomFormatEtc.cfFormat = m_uiCustomFormat;
sCustomFormatEtc.ptd = NULL;
sCustomFormatEtc.dwAspect = 0;
sCustomFormatEtc.lindex = -1;
sCustomFormatEtc.tymed = TYMED_HGLOBAL;
// if we have already allocated the data
if(sCustomStgMedium.hGlobal)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -