📄 extrichedit.cpp
字号:
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 + -