⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atlcontrolwin.cpp

📁 用VC开发activex 一书实例1 ATLControl
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	// if there is an old brush
	if(hOldBrush)
	{
		// get the DC
		HDC hDC = this->GetDC();

		// select the old brush back
		::SelectObject(hDC, hOldBrush);

		// release the DC
		this->ReleaseDC(hDC);
	}

	// if we created a brush
	if(hBrush)
		// destroy the brush we created
		::DeleteObject(hBrush);

	return TRUE;
}

static FONTDESC _fdDefault = 
{
    sizeof(FONTDESC),
    L"MS Sans Serif",
    FONTSIZE(8),
    FW_NORMAL,
    DEFAULT_CHARSET,
    FALSE,
    FALSE,
    FALSE
};

void CATLControlWin::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 CATLControlWin::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;
}

STDMETHODIMP CATLControlWin::get_ReadyState(long * pVal)
{
	// set the return value to the value of the member variable
	*pVal = m_lReadyState;

	return S_OK;
}

STDMETHODIMP CATLControlWin::get_TextDataPath(BSTR * pVal)
{
	// return a copy of the member variable
	*pVal = m_bstrTextDataPath.Copy();

	return S_OK;
}

STDMETHODIMP CATLControlWin::put_TextDataPath(BSTR newVal)
{
	HRESULT hResult = S_OK;

	// copy the new string to the member variable
	m_bstrTextDataPath = newVal;

	// start the asynchronous download of the data
	CBindStatusCallback<CATLControlWin>::Download(this, OnData, m_bstrTextDataPath, m_spClientSite, FALSE);

	// let the container know that the property has changed
	this->SetDirty(TRUE);
	// this->SetModifiedFlag(); <== MFC version

	return hResult;
}

//OnData will be used as a callback functin by the CBindStatusCallback object.
//OnData will be called periodically with data from the asynchronous transfer
void CATLControlWin::OnData(CBindStatusCallback<CATLControlWin>* pbsc, BYTE* pBytes, DWORD dwSize)
{
	// if we have not read any data yet
	if(pbsc->m_dwTotalRead == 0)
	{
		// clear the buffer
		m_bstrText = _T("");

		// set the ready state of the control
		m_lReadyState = READYSTATE_LOADING;

		// let the container know that the property has changed
		this->Fire_ReadyStateChange();
	}

	// add the data to our buffer
	m_bstrText.Append((LPCSTR) pBytes);	

	long lRetVal;
	VARIANT varAlignment;

	// initialize the variant
	::VariantInit(&varAlignment);
	
	// defer to the CaptionMethod implementation
	this->CaptionMethod(m_bstrText, 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

	// if there is nothing left
	if(pbsc->m_dwAvailableToRead == 0)
	{
		// set the ready state of the control
		m_lReadyState = READYSTATE_COMPLETE;

		// let the container know that the property has changed
		this->Fire_ReadyStateChange();
	}
}

STDMETHODIMP CATLControlWin::MapPropertyToPage(DISPID dispID, CLSID *pClsid)
{
	// if this is the dispid property
	if(dispID == dispidAlignment)
		// defer to the property enumeration and not the property page
		return E_NOTIMPL;
	else
		// defer to the base class implementation
		return IPerPropertyBrowsingImpl<CATLControlWin>::MapPropertyToPage(dispID, pClsid);
}

STDMETHODIMP CATLControlWin::GetPredefinedStrings(DISPID dispid, CALPOLESTR * lpcaStringsOut, CADWORD * lpcaCookiesOut)
{
	USES_CONVERSION;
	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] = ATLA2WHELPER((LPWSTR)::CoTaskMemAlloc((lstrlen(EALIGN_LEFT_TEXT) + 1) * 2), EALIGN_LEFT_TEXT, lstrlen(EALIGN_LEFT_TEXT) + 1);
		lpcaStringsOut->pElems[1] = ATLA2WHELPER((LPWSTR)::CoTaskMemAlloc((lstrlen(EALIGN_CENTER_TEXT) + 1) * 2), EALIGN_CENTER_TEXT, lstrlen(EALIGN_CENTER_TEXT) + 1);
		lpcaStringsOut->pElems[2] = ATLA2WHELPER((LPWSTR)::CoTaskMemAlloc((lstrlen(EALIGN_RIGHT_TEXT) + 1) * 2), EALIGN_RIGHT_TEXT, lstrlen(EALIGN_RIGHT_TEXT) + 1);

		// 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 CATLControlWin::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 CATLControlWin::GetDisplayString(DISPID dispid, BSTR* lpbstr)
{
	USES_CONVERSION;

	HRESULT hResult = S_FALSE;

	// which property is it
	switch(dispid)
	{
	case dispidAlignment:
	{
		switch(m_lAlignment)
		{
		case EALIGN_LEFT:
			*lpbstr = ::SysAllocString(T2OLE(EALIGN_LEFT_TEXT));
		break;
		case EALIGN_CENTER:
			*lpbstr = ::SysAllocString(T2OLE(EALIGN_CENTER_TEXT));
		break;
		case EALIGN_RIGHT:
			*lpbstr = ::SysAllocString(T2OLE(EALIGN_RIGHT_TEXT));
		break;
		}

		// set the return value
		hResult = S_OK;
	}
	break;
	}

	return hResult;
}

LRESULT CATLControlWin::OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled)
{
	UINT nChar = wParam;
	UINT nRepCnt = LOWORD(lParam);
	UINT nFlags = HIWORD(lParam);

  	// find out if the shift key is being held down
	short sShift = ::GetKeyState(VK_SHIFT);
  	// find out if the control key is being held down
	short sControl = ::GetKeyState(VK_CONTROL);

	switch(nChar)
	{
	// PASTE
	case 0x56: // 'V'
	case 0x76: // 'v'					 
		// if the control key is being held down
		if(sControl & 0x8000)
		{
			// get any text from the clipboard
			this->GetDataFromClipboard();

			// force the control to repaint itself
			this->FireViewChange();
//			this->InvalidateControl(); <== MFC Version

			// we don't need to pass this key to the base implementation
			bHandled = TRUE;
		}
	break;
	// COPY or PASTE
	case 0x43: // 'C'
	case 0x63: // 'c'					 
	case VK_INSERT:
		// if the control key is being held down
		if(sControl & 0x8000)
		{
			// copy the data to the clipboard
			this->CopyDataToClipboard();

			// we don't need to pass this key to the base implementation
			bHandled = TRUE;
		}
		// if the shift key is being held down it is a PASTE
		else if(sShift & 0x8000 && nChar == VK_INSERT)
		{
			// get any text from the clipboard
			this->GetDataFromClipboard();

			// force the control to repaint itself
			this->FireViewChange();
//			this->InvalidateControl(); <== MFC Version

			// we don't need to pass this key to the base implementation
			bHandled = TRUE;
		}
	break;
	// CUT
	case 0x58: // 'X'
	case 0x78: // 'x'
	case VK_DELETE:
		// if this is a shift delete OR CTRL-X/x
		if((nChar == VK_DELETE && (sShift & 0x8000)) || 
			((nChar == 0x58 || nChar == 0x78) && (sControl & 0x8000)))
		{
			this->CopyDataToClipboard();

			// clear the string since this is a CUT operation
			delete [] m_lptstrCaption;

			// NULL terminate the string reference
			m_lptstrCaption = new TCHAR[1];
			m_lptstrCaption[0] = '\0';

			// fire the global change event
			this->FireChange();

			// force the control to repaint itself
			this->FireViewChange();
//			this->InvalidateControl(); <== MFC Version

			// we don't need to pass this key to the base implementation
			bHandled = TRUE;
		}
	break;
	}

	return TRUE;
}

void CATLControlWin::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(reinterpret_cast<IDataObject*>
			(static_cast<IDataObjectImpl<CATLControlWin>*>(this)));
	}
}

void CATLControlWin::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';

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -