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

📄 extrichedit.cpp

📁 类似QQ,MSN表情的richedit,用来测试表情控件的
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		if(GetKeyState(VK_CONTROL) < 0)   
			cut_data();
		break;
	case 'V':   //全屏显示
		if(GetKeyState(VK_CONTROL) < 0)   
			paste_data();
		break;
	case VK_DELETE:   //全屏显示
		delet_data();
		break;
	default:
		break;
	}*/
	CRichEditCtrl::OnKeyDown(nChar, nRepCnt, nFlags);	
}
//初始化表情文件转义字符串
void CExtRichEdit::InitFaceStr()
{
	for(int i = 0;i < 2;i ++)
	{

		facestr[i][0] = facestr[i][1] = ':';
	}
	facestr[0][2] = ')';
	facestr[1][2] = '(';
	facestr[0][3] = facestr[1][3] = 0;
}



//插入默认的gif文件
//参数:faceindexgif文件的index
void CExtRichEdit::InsertFace(int faceindex)
{
	CString strPicPath;
	strPicPath.Format("face\\%d.gif",faceindex);
	LPLOCKBYTES lpLockBytes = NULL;
	SCODE sc;
	HRESULT hr;
	//print to RichEdit' s IClientSite
	LPOLECLIENTSITE m_lpClientSite;
	//A smart point to IAnimator
	IImageShowPtr   m_lpImageShow;
	//IGifAnimatorPtr	m_lpAnimator;
	//ptr 2 storage	
	LPSTORAGE m_lpStorage;
	//the object 2 b insert 2
	LPOLEOBJECT	m_lpObject;
	//Create lockbytes
	sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);
	if (sc != S_OK)
		AfxThrowOleException(sc);
	ASSERT(lpLockBytes != NULL);

	//use lockbytes to create storage
	sc = ::StgCreateDocfileOnILockBytes(lpLockBytes,
		STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &m_lpStorage);
	if (sc != S_OK)
	{
		VERIFY(lpLockBytes->Release() == 0);
		lpLockBytes = NULL;
		AfxThrowOleException(sc);
	}
	ASSERT(m_lpStorage != NULL);

	//get the ClientSite of the very RichEditCtrl
	GetIRichEditOle()->GetClientSite(&m_lpClientSite);
	ASSERT(m_lpClientSite != NULL);

	try
	{
		//Initlize COM interface
		hr = ::CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ); //ok
		if( FAILED(hr) )
			_com_issue_error(hr);

		//Get GifAnimator object
		//here, I used a smart point, so I do not need to free it
		hr = /*m_lpAnimator*/m_lpImageShow.CreateInstance(/*CLSID_GifAnimator*/CLSID_ImageShow);	    //ok
		if( FAILED(hr) )
			_com_issue_error(hr);
		//COM operation need BSTR, so get a BSTR
		BSTR path = strPicPath.AllocSysString();

		//Load the gif
		hr = /*m_lpAnimator->LoadFromFile(path)*/m_lpImageShow->put_FileName(path);                          //
		if( FAILED(hr) )
			_com_issue_error(hr);

		//TRACE0( /*m_lpAnimator->GetFilePath()*/m_lpImageShow.get_FileName() );

		//get the IOleObject
		hr = /*m_lpAnimator*/m_lpImageShow.QueryInterface(IID_IOleObject, (void**)&m_lpObject);
		if( FAILED(hr) )
			_com_issue_error(hr);

		//Set it 2 b inserted
		OleSetContainedObject(m_lpObject, TRUE);

		//2 insert in 2 richedit, you need a struct of REOBJECT
		REOBJECT reobject;
		ZeroMemory(&reobject, sizeof(REOBJECT));

		reobject.cbStruct = sizeof(REOBJECT);	
		CLSID clsid;
		sc = m_lpObject->GetUserClassID(&clsid);
		if (sc != S_OK)
			AfxThrowOleException(sc);
		//set clsid
		reobject.clsid = clsid;
		//can be selected
		reobject.cp = REO_CP_SELECTION;
		//content, but not static
		reobject.dvaspect = DVASPECT_CONTENT;
		//goes in the same line of text line
		reobject.dwFlags = REO_BELOWBASELINE; //REO_RESIZABLE |
		reobject.dwUser = 0;
		//the very object
		reobject.poleobj = m_lpObject;
		//client site contain the object
		reobject.polesite = m_lpClientSite;
		//the storage 
		reobject.pstg = m_lpStorage;

		SIZEL sizel;
		sizel.cx = sizel.cy = 0;
		reobject.sizel = sizel;
		HWND hWndRT = this->m_hWnd;
	
		GetIRichEditOle()->InsertObject(&reobject);
		::SendMessage(hWndRT, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0);
		VARIANT_BOOL ret;
		//do frame changing
		ret = /*m_lpAnimator->TriggerFrameChange()*/m_lpImageShow->Play();
		//show it
		m_lpObject->SetClientSite(m_lpClientSite);
		m_lpObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, m_lpClientSite, 0, m_hWnd, NULL);
		m_lpObject->DoVerb(OLEIVERB_SHOW, NULL, m_lpClientSite, 0, m_hWnd, NULL);

		//redraw the window to show animation
		RedrawWindow();

		if (m_lpClientSite)
		{
			m_lpClientSite->Release();
			m_lpClientSite = NULL;
		}
		if (m_lpObject)
		{
			m_lpObject->Release();
			m_lpObject = NULL;
		}
		if (m_lpStorage)
		{
			m_lpStorage->Release();
			m_lpStorage = NULL;
		}

		SysFreeString(path);
	}
	catch( _com_error e )
	{
		AfxMessageBox(e.ErrorMessage());
		::CoUninitialize();	
	}
	long InsertP;
	GetSel(InsertP,InsertP);       //将图标看成是一个字符
	InsertP --;
	FacePosition faceNode;		//faceNode中存储的是在哪个位置插入,插入哪一个表情。
	int m,gifcount,bmpcount ;
	m = GetFrontText(InsertP,gifcount,bmpcount);
	int c = GetIRichEditOle()->GetObjectCount();
	faceNode.nPos = m ;      //
	faceNode.nFaceIndex = faceindex;
	faceNode.facecount = gifcount + bmpcount;
	vecFace.insert(vecFace.begin() + gifcount + bmpcount,faceNode);	
	for(int i = gifcount + 1 ;i < vecFace.size();i ++ )
	{
		vecFace[i].facecount = vecFace[i].facecount ++;
		vecFace[i].nPos = vecFace[i].nPos + 1;                    //更新vecFace 插入picture后 后面的pictrue位置都后移了一个字符
	}
	for(int i = bmpcount; i < vecbmp.size();i ++)
	{
		vecbmp[i].nPos = vecbmp[i].nPos + 1;                 //更新vecbmp 插入picture后 后面的pictrue位置都后移了一个字符
	}
	m_facecount ++;
}
//以文件名方式插入pictrue
//参数:faceindex表情文件的index faceindex == -1时插入的文件不是默认的gif文件
void CExtRichEdit::InsertFace(CString strPicPath,int faceindex)
{
	LPLOCKBYTES lpLockBytes = NULL;
	SCODE sc;
	HRESULT hr;
	//print to RichEdit' s IClientSite
	LPOLECLIENTSITE m_lpClientSite;
	//A smart point to IAnimator
	IImageShowPtr   m_lpImageShow;
	//IGifAnimatorPtr	m_lpAnimator;
	//ptr 2 storage	
	LPSTORAGE m_lpStorage;
	//the object 2 b insert 2
	LPOLEOBJECT	m_lpObject;

	//Create lockbytes
	sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);
	if (sc != S_OK)
		AfxThrowOleException(sc);
	ASSERT(lpLockBytes != NULL);
	
	//use lockbytes to create storage
	sc = ::StgCreateDocfileOnILockBytes(lpLockBytes,
		STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &m_lpStorage);
	if (sc != S_OK)
	{
		VERIFY(lpLockBytes->Release() == 0);
		lpLockBytes = NULL;
		AfxThrowOleException(sc);
	}
	ASSERT(m_lpStorage != NULL);
	
	//get the ClientSite of the very RichEditCtrl
	GetIRichEditOle()->GetClientSite(&m_lpClientSite);
	ASSERT(m_lpClientSite != NULL);

	try
	{
		//Initlize COM interface
		hr = ::CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ); //ok
		if( FAILED(hr) )
			_com_issue_error(hr);
		
		//Get GifAnimator object
		//here, I used a smart point, so I do not need to free it
		hr = /*m_lpAnimator*/m_lpImageShow.CreateInstance(/*CLSID_GifAnimator*/CLSID_ImageShow);	    //ok
		if( FAILED(hr) )
				_com_issue_error(hr);
		//COM operation need BSTR, so get a BSTR
		BSTR path = strPicPath.AllocSysString();

		//Load the gif
		hr = m_lpImageShow->put_FileName(path);//m_lpAnimator->LoadFromFile(path);                          //
		if( FAILED(hr) )
			_com_issue_error(hr);
			
		//TRACE0( /*m_lpAnimator->getFilePath()*/m_lpImageShow.get_FileName() );
		
		//get the IOleObject
		hr = /*m_lpAnimator*/m_lpImageShow->QueryInterface(IID_IOleObject, (void**)&m_lpObject);
		if( FAILED(hr) )
			_com_issue_error(hr);
		
		//Set it 2 b inserted
		OleSetContainedObject(m_lpObject, TRUE);
		
		//2 insert in 2 richedit, you need a struct of REOBJECT
		REOBJECT reobject;
		ZeroMemory(&reobject, sizeof(REOBJECT));

		reobject.cbStruct = sizeof(REOBJECT);	
		CLSID clsid;
		sc = m_lpObject->GetUserClassID(&clsid);
		if (sc != S_OK)
			AfxThrowOleException(sc);
		//set clsid
		reobject.clsid = clsid;
		//can be selected
		reobject.cp = REO_CP_SELECTION;
		//content, but not static
		reobject.dvaspect = DVASPECT_CONTENT;
		//goes in the same line of text line
		reobject.dwFlags = REO_BELOWBASELINE; //REO_RESIZABLE |
		reobject.dwUser = 0;
		//the very object
		reobject.poleobj = m_lpObject;
		//client site contain the object
		reobject.polesite = m_lpClientSite;
		//the storage 
		reobject.pstg = m_lpStorage;
		
		SIZEL sizel;
		sizel.cx = sizel.cy = 0;
		reobject.sizel = sizel;
		HWND hWndRT = this->m_hWnd;

		GetIRichEditOle()->InsertObject(&reobject);
		
		::SendMessage(hWndRT, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0);
		VARIANT_BOOL ret;
		//do frame changing
		ret = m_lpImageShow->Play();//m_lpAnimator->TriggerFrameChange();
		//show it
		m_lpObject->SetClientSite(m_lpClientSite);
		m_lpObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, m_lpClientSite, 0, m_hWnd, NULL);
		m_lpObject->DoVerb(OLEIVERB_SHOW, NULL, m_lpClientSite, 0, m_hWnd, NULL);
		
		//redraw the window to show animation
		RedrawWindow();

		if (m_lpClientSite)
		{
			m_lpClientSite->Release();
			m_lpClientSite = NULL;
		}
		if (m_lpObject)
		{
			m_lpObject->Release();
			m_lpObject = NULL;
		}
		if (m_lpStorage)
		{
			m_lpStorage->Release();
			m_lpStorage = NULL;
		}
		
		SysFreeString(path);
	}
	catch( _com_error e )
	{
		AfxMessageBox(e.ErrorMessage());
		::CoUninitialize();	
	}
	if(faceindex == - 1)
		m_bmpcount ++;
	m_facecount ++;

}

//插入以转义字符形式的pictrue
//参数:str要插入的字符串 包括转义字符 InsertP要插入的位置
void CExtRichEdit::InsertText(CString &str,long InsertP )
{  
	int frontface = 0,frontbmp = 0;
	GetSel(InsertP,InsertP);       //将图标看成是一个字符
	if(InsertP != 0)
		frontface = GetFaceCount(InsertP);
	if(InsertP != 0)
		frontbmp = GetBmpCount(InsertP);
	SetSel(InsertP,InsertP);
	ReplaceSel(str,true);
	int count = 0,bmpcount = 0;
	vector<FacePosition> temfacepos;
	for(int i = 0, m = -1; i< 2; i++)
	{
		//关键的一步:查找宽字符,汉字算一个字符。放在循环中,就可以查找重复的字符。
		while(1)
		{
			m = (int)str.Find(facestr[i], m + 1);	//循环搜索,不放过重复的表情
			if(m == -1)
				break;
			FacePosition faceNode;		//faceNode中存储的是在哪个位置插入,插入哪一个表情。
			faceNode.nFaceIndex = i;
			int t = m + InsertP;
			faceNode.nPos = t ;
			faceNode.facecount = frontface;
			temfacepos.push_back(faceNode);
			count ++;
		}
	}	//查找完0毕
	int pos = -1;
	while(1)
	{
		pos = (int)str.Find('{', pos + 1);	//循环搜索,不放过重复的表情
		if(pos == -1)
			break;
		FacePosition bmpNode;		//faceNode中存储的是在哪个位置插入,插入哪一个表情。
		bmpNode.facecount = frontbmp;
		int t = pos + InsertP;
		bmpNode.nPos = t ;
		bmpNode.nFaceIndex = -1;
		temfacepos.push_back(bmpNode);
		bmpcount ++;
	}
	bool less_than(FacePosition &face1, FacePosition &face2);	//声明排序的"条件"函数
	sort(temfacepos.begin(), temfacepos.end(),less_than);	//详见我的ObjectSort工程中的说明。可参见《Essential C++》P84
	int newbmp = 0,newgif = 0;
	for(int i = 0;i < count + bmpcount ;i ++)
	{
		temfacepos[i].facecount = temfacepos[i].facecount + i;
		if(temfacepos[i].nFaceIndex != -1)

⌨️ 快捷键说明

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