www.pudn.com > TestIconPicker.zip > RichEditCtrlEx.cpp, change:2004-03-31,size:11149b


// RichEditCtrlEx.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "RichEditCtrlEx.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
 
#define ID_RICH_UNDO                    101 
#define ID_RICH_CUT                     102 
#define ID_RICH_COPY                    103 
#define ID_RICH_PASTE                   104 
#define ID_RICH_CLEAR                   105 
#define ID_RICH_SELECTALL               106 
#define ID_RICH_SETFONT                 107 
 
///////////////////////////////////////////////////////////////////////////// 
// CRichEditCtrlEx 
LPUNKNOWN AFXAPI _AfxQueryInterface(LPUNKNOWN lpUnknown, REFIID iid) 
{ 
	ASSERT(lpUnknown != NULL); 
 
	LPUNKNOWN lpW = NULL; 
	if (lpUnknown->QueryInterface(iid, (void **)&lpW) != S_OK) 
		return NULL; 
 
	return lpW; 
} 
 
CRichEditCtrlEx::CRichEditCtrlEx() 
{ 
} 
 
CRichEditCtrlEx::~CRichEditCtrlEx() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(CRichEditCtrlEx, CRichEditCtrl) 
	//{{AFX_MSG_MAP(CRichEditCtrlEx) 
	ON_WM_RBUTTONUP() 
	ON_COMMAND(ID_RICH_COPY, OnCopy) 
	ON_COMMAND(ID_RICH_CUT, OnCut) 
	ON_COMMAND(ID_RICH_PASTE, OnPaste) 
	ON_COMMAND(ID_RICH_SELECTALL, OnSelectall) 
	ON_COMMAND(ID_RICH_UNDO, OnUndo) 
	ON_COMMAND(ID_RICH_CLEAR, OnClear) 
	ON_COMMAND(ID_RICH_SETFONT, OnSelectfont) 
	ON_WM_CREATE() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CRichEditCtrlEx message handlers 
 
 
///插入位图,从文件中读入 
void CRichEditCtrlEx::InsertBitmap(CString szFileName) 
{ 
	USES_CONVERSION; 
	SCODE sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &m_lpLockBytes); 
	if (sc != S_OK) 
		AfxThrowOleException(sc); 
	ASSERT(m_lpLockBytes != NULL); 
 
	sc = ::StgCreateDocfileOnILockBytes(m_lpLockBytes, 
		STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &m_lpStorage); 
	if (sc != S_OK) 
	{ 
		VERIFY(m_lpLockBytes->Release() == 0); 
		m_lpLockBytes = NULL; 
		AfxThrowOleException(sc); 
	} 
 
    //CString szFileName( _T("C:\\Dev\\RTFBitmap\\reportplot.bmp") ); 
 
	// attempt to create the object 
	sc = ::OleCreateFromFile(CLSID_NULL, T2COLE(szFileName), 
							 IID_IUnknown, OLERENDER_DRAW, NULL, NULL,  
							 m_lpStorage, (void **)&m_lpObject); 
	if ( sc != S_OK ) 
	{ 
		TCHAR * lpMsgBuf; 
		::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |  
						 FORMAT_MESSAGE_FROM_SYSTEM, NULL,  
						 ::GetLastError(), 
						 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
						 (LPTSTR) &lpMsgBuf, 0, NULL ); 
		CString msg( lpMsgBuf ); 
		msg += _T("\n\n\nThe following file, created in\n" 
				  "Simulation->Plot, may be missing due\n" 
				  "to not doing a File->Save Workspace:\n\n" ); 
		msg += szFileName; 
		AfxMessageBox( msg, MB_OK ); 
		::LocalFree( lpMsgBuf ); 
		return; 
	} 
	 
	// m_lpObject is currently an IUnknown, convert to IOleObject 
	if (m_lpObject != NULL) 
	{ 
		LPUNKNOWN lpUnk = m_lpObject; 
		m_lpObject = QUERYINTERFACE(lpUnk, IOleObject); 
		lpUnk->Release(); 
		if (m_lpObject == NULL) 
			AfxThrowOleException(E_OUTOFMEMORY); 
	} 
 
	// cache the IViewObject interface 
	m_lpViewObject = QUERYINTERFACE(m_lpObject, IViewObject2); 
	if (m_lpViewObject == NULL) 
		return; 
 
	// setup for advises; we assume that OLE cleans them up properly 
	LPADVISESINK lpAdviseSink = 
		(LPADVISESINK)GetInterface(&IID_IAdviseSink); 
 
	// set up view advise 
	VERIFY(m_lpViewObject->SetAdvise(DVASPECT_CONTENT, 0, lpAdviseSink) 
		== S_OK); 
 
	// the server shows these in its user-interface 
	//  (as document title and in File Exit menu) 
	m_lpObject->SetHostNames(T2COLE(AfxGetAppName()), 
		T2COLE(_T("Test"))); 
 
	// all items are "contained" -- this makes our reference to this object 
	//  weak -- which is needed for links to embedding silent update. 
	OleSetContainedObject(m_lpObject, TRUE); 
 
	CHARRANGE cr; 
	this->GetSel( cr ); 
	cr.cpMin = cr.cpMax -1; 
	this->SetSel( cr ); 
 
	REOBJECT reo; 
	memset( &reo, 0, sizeof( reo ) ); 
	reo.cbStruct = sizeof( reo ); 
	CLSID classID; 
	if ( m_lpObject->GetUserClassID( &classID ) != S_OK) 
		classID = CLSID_NULL; 
	reo.clsid = classID; 
	reo.cp = REO_CP_SELECTION; 
	reo.poleobj = m_lpObject; 
	reo.pstg = m_lpStorage; 
	LPOLECLIENTSITE lpClientSite; 
	this->GetIRichEditOle()->GetClientSite( &lpClientSite ); 
	reo.polesite = lpClientSite; 
	SIZEL sizel; 
	sizel.cx = sizel.cy = 0; // let richedit determine initial size 
	reo.sizel = sizel; 
	reo.dvaspect = DVASPECT_CONTENT; 
	reo.dwFlags = REO_RESIZABLE; 
	reo.dwUser = 0; 
	HRESULT hr = this->GetIRichEditOle()->InsertObject( &reo ); 
 
} 
 
///生成右键菜单 
void CRichEditCtrlEx::OnRButtonUp(UINT nFlags, CPoint point)  
{ 
	// TODO: Add your message handler code here and/or call default 
	//设置为焦点 
	SetFocus(); 
	//创建一个弹出式菜单 
	CMenu popmenu; 
	popmenu.CreatePopupMenu(); 
	//添加菜单项目 
	popmenu.AppendMenu(0, ID_RICH_UNDO, "&Undo"); 
	popmenu.AppendMenu(0, MF_SEPARATOR); 
	popmenu.AppendMenu(0, ID_RICH_CUT, "&Cut"); 
	popmenu.AppendMenu(0, ID_RICH_COPY, "C&opy"); 
	popmenu.AppendMenu(0, ID_RICH_PASTE, "&Paste"); 
	popmenu.AppendMenu(0, ID_RICH_CLEAR, "C&lear"); 
	popmenu.AppendMenu(0, MF_SEPARATOR); 
	popmenu.AppendMenu(0, ID_RICH_SELECTALL, "Select &All"); 
	popmenu.AppendMenu(0, MF_SEPARATOR); 
	popmenu.AppendMenu(0, ID_RICH_SETFONT, "Select &Font"); 
 
	//初始化菜单项 
	UINT nUndo=(CanUndo() ? 0 : MF_GRAYED ); 
	popmenu.EnableMenuItem(ID_RICH_UNDO, MF_BYCOMMAND|nUndo); 
 
	UINT nSel=((GetSelectionType()!=SEL_EMPTY) ? 0 : MF_GRAYED) ; 
	popmenu.EnableMenuItem(ID_RICH_CUT, MF_BYCOMMAND|nSel); 
	popmenu.EnableMenuItem(ID_RICH_COPY, MF_BYCOMMAND|nSel); 
	popmenu.EnableMenuItem(ID_RICH_CLEAR, MF_BYCOMMAND|nSel); 
	 
	UINT nPaste=(CanPaste() ? 0 : MF_GRAYED) ; 
	popmenu.EnableMenuItem(ID_RICH_PASTE, MF_BYCOMMAND|nPaste); 
 
	//显示菜单 
	CPoint pt; 
	GetCursorPos(&pt); 
	popmenu.TrackPopupMenu(TPM_RIGHTBUTTON, pt.x, pt.y, this); 
	popmenu.DestroyMenu(); 
	CRichEditCtrl::OnRButtonDown(nFlags, point); 
	CRichEditCtrl::OnRButtonUp(nFlags, point); 
} 
 
///设置字体 
void CRichEditCtrlEx::OnSelectfont()  
{ 
	// TODO: Add your command handler code here 
	CHARFORMAT cf; 
	LOGFONT lf; 
	memset(&cf, 0, sizeof(CHARFORMAT)); 
	memset(&lf, 0, sizeof(LOGFONT)); 
	//判断是否选择了内容 
	BOOL m_bSelect = (GetSelectionType() != SEL_EMPTY) ? TRUE : FALSE; 
	if (m_bSelect) 
	{ 
		GetSelectionCharFormat(cf); 
	} 
	else 
	{ 
		GetDefaultCharFormat(cf); 
	} 
	//得到相关字体属性 
	BOOL bIsBold = cf.dwEffects & CFE_BOLD; 
	BOOL bIsItalic = cf.dwEffects & CFE_ITALIC; 
	BOOL bIsUnderline = cf.dwEffects & CFE_UNDERLINE; 
	BOOL bIsStrickout = cf.dwEffects & CFE_STRIKEOUT; 
	//设置属性 
	lf.lfCharSet = cf.bCharSet; 
	lf.lfHeight = cf.yHeight/15; 
	lf.lfPitchAndFamily = cf.bPitchAndFamily; 
	lf.lfItalic = bIsItalic; 
	lf.lfWeight = (bIsBold ? FW_BOLD : FW_NORMAL); 
	lf.lfUnderline = bIsUnderline; 
	lf.lfStrikeOut = bIsStrickout; 
	sprintf(lf.lfFaceName, cf.szFaceName); 
	 
	CFontDialog dlg(&lf); 
	dlg.m_cf.rgbColors = cf.crTextColor; 
	if (dlg.DoModal() == IDOK) 
	{ 
		dlg.GetCharFormat(cf);//获得所选字体的属性 
		if (m_bSelect)  
			SetSelectionCharFormat(cf);	//为选定的内容设定所选字体 
		else 
			SetWordCharFormat(cf);	//为将要输入的内容设定字体 
	} 
	 
 
} 
 
 
 
int CRichEditCtrlEx::OnCreate(LPCREATESTRUCT lpCreateStruct)  
{ 
	if (CRichEditCtrl::OnCreate(lpCreateStruct) == -1) 
		return -1; 
	 
	// TODO: Add your specialized creation code here 
	this->SetFont(GetParent()->GetFont()); 
	return 0; 
} 
 
///根据句柄插入位图 
void CRichEditCtrlEx::InsertBitmap(HBITMAP hBitmap) 
{ 
	STGMEDIUM stgm; 
	stgm.tymed = TYMED_GDI;	   // Storage medium = HBITMAP handle 
	stgm.hBitmap = hBitmap; 
	stgm.pUnkForRelease = NULL; // Use ReleaseStgMedium 
	 
	FORMATETC fm; 
	fm.cfFormat = CF_BITMAP;				// Clipboard format = CF_BITMAP 
	fm.ptd = NULL;							// Target Device = Screen 
	fm.dwAspect = DVASPECT_CONTENT;			// Level of detail = Full content 
	fm.lindex = -1;							// Index = Not applicaple 
	fm.tymed = TYMED_GDI;		 
 
	////创建输入数据源 
	IStorage *pStorage;	 
	     
	     ///分配内存 
	LPLOCKBYTES lpLockBytes = NULL; 
	SCODE sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes); 
	if (sc != S_OK) 
		AfxThrowOleException(sc); 
	ASSERT(lpLockBytes != NULL); 
	 
	sc = ::StgCreateDocfileOnILockBytes(lpLockBytes, 
		STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &pStorage); 
	if (sc != S_OK) 
	{ 
		VERIFY(lpLockBytes->Release() == 0); 
		lpLockBytes = NULL; 
		AfxThrowOleException(sc); 
	} 
	ASSERT(pStorage != NULL); 
 
	COleDataSource *pDataSource = new COleDataSource; 
	pDataSource->CacheData(CF_BITMAP, &stgm); 
	LPDATAOBJECT lpDataObject =  
		(LPDATAOBJECT)pDataSource->GetInterface(&IID_IDataObject); 
 
	///获取RichEdit的OLEClientSite 
	LPOLECLIENTSITE lpClientSite; 
	this->GetIRichEditOle()->GetClientSite( &lpClientSite ); 
 
 
	///创建OLE对象 
	IOleObject *pOleObject; 
	sc = OleCreateStaticFromData(lpDataObject,IID_IOleObject,OLERENDER_FORMAT, 
		&fm,lpClientSite,pStorage,(void **)&pOleObject); 
	if(sc!=S_OK) 
		AfxThrowOleException(sc); 
 
	///插入OLE对象 
 
	REOBJECT reobject; 
	ZeroMemory(&reobject, sizeof(REOBJECT)); 
	reobject.cbStruct = sizeof(REOBJECT); 
	 
	CLSID clsid; 
	sc = pOleObject->GetUserClassID(&clsid); 
	if (sc != S_OK) 
		AfxThrowOleException(sc); 
 
	reobject.clsid = clsid; 
	reobject.cp = REO_CP_SELECTION; 
	reobject.dvaspect = DVASPECT_CONTENT; 
	reobject.poleobj = pOleObject; 
	reobject.polesite = lpClientSite; 
	reobject.pstg = pStorage; 
 
	HRESULT hr = this->GetIRichEditOle()->InsertObject( &reobject ); 
 
} 
 
////返回RTF格式化字符串 
CString CRichEditCtrlEx::GetRTF() 
{ 
	EDITSTREAM es; 
	es.dwError = 0; 
	es.pfnCallback = RTFFormatToCString;		// Set the callback 
 
	CString sRTF = ""; 
 
	es.dwCookie = (DWORD) &sRTF;	// so sRTF receives the string 
	 
	StreamOut(SF_RTF, es);			// Call CRichEditCtrl::StreamOut to get the string. 
	/// 
 
	return sRTF; 
 
} 
 
void CRichEditCtrlEx::SetRTF(CString strRTF) 
{ 
	EDITSTREAM es; 
	es.dwError = 0; 
	es.pfnCallback = CStringFormatToRTF; 
	es.dwCookie = (DWORD) &strRTF; 
	StreamIn(SF_RTF, es);	// Do it. 
 
} 
 
////StreamOut的回调函数 
DWORD CALLBACK CRichEditCtrlEx::RTFFormatToCString(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) 
{ 
	CString *psEntry = (CString*) dwCookie; 
	 
 
	///把数据存放在一个临时变量里 
	CString tmpEntry = ""; 
	tmpEntry = (CString) pbBuff; 
 
	// And write it!!! 
	//把实际有效的数据返回 
	*psEntry += tmpEntry.Left(cb); 
	 
	return 0; 
} 
 
////StreamIn的回调函数 *pcb是实际输入的字节数,cb是一次输入的最大字节数 
DWORD CALLBACK CRichEditCtrlEx::CStringFormatToRTF(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) 
{ 
	CString *pstr = (CString *) dwCookie; 
 
	////若要存放到RichEdit的数据长度小于一次能存放的最大长度,则 
	////一次性输入到RichEdit中 
	if (pstr->GetLength() < cb) 
	{ 
		*pcb = pstr->GetLength(); 
		memcpy(pbBuff, (LPCSTR) *pstr, *pcb); 
		pstr->Empty(); 
	} 
 
	////若输入的数据太多,则一次输入cb字节到RichEdit中 
	///StreamIn回递归调用这个函数 
	else 
	{ 
		*pcb = cb; 
		memcpy(pbBuff, (LPCSTR) *pstr, *pcb); 
		*pstr = pstr->Right(pstr->GetLength() - cb); 
	} 
 
	 
	return 0; 
}