// RichEditEx.cpp : implementation file // #include "stdafx.h" //#include "Exppp.h" #include "RichEditEx.h" #include #include //使用了QQ的图像处理控件 //#import "ImageOle.dll" named_guids #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CRichEditEx CRichEditEx::CRichEditEx() { } CRichEditEx::~CRichEditEx() { } BEGIN_MESSAGE_MAP(CRichEditEx, CRichEditCtrl) //{{AFX_MSG_MAP(CRichEditEx) ON_WM_RBUTTONDOWN() 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) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CRichEditEx message handlers void CRichEditEx::OnRButtonDown(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, _T("撤消(&U)") ); popmenu.AppendMenu(0, MF_SEPARATOR); popmenu.AppendMenu(0, ID_RICH_CUT, _T("剪切(&T)")); popmenu.AppendMenu(0, ID_RICH_COPY, _T("复制(&C)")); popmenu.AppendMenu(0, ID_RICH_PASTE, _T("粘贴(&P)")); popmenu.AppendMenu(0, ID_RICH_CLEAR, _T("清空(&L)")); popmenu.AppendMenu(0, MF_SEPARATOR); popmenu.AppendMenu(0, ID_RICH_SELECTALL, _T("全选(&A)") ); //初始化菜单项 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); } void CRichEditEx::SetFont() { 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; _stprintf(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); //为将要输入的内容设定字体 } } void CRichEditEx::SetColor2(COLORREF color) { CHARFORMAT cf; ZeroMemory(&cf, sizeof(CHARFORMAT)); cf.cbSize = sizeof(CHARFORMAT); cf.dwMask = CFM_COLOR; cf.crTextColor = color; SetWordCharFormat(cf); } void CRichEditEx::StartIndent2(long lStartIndent) { PARAFORMAT2 pf2; ZeroMemory(&pf2, sizeof(PARAFORMAT2)); pf2.cbSize = sizeof(PARAFORMAT2); pf2.dwMask = PFM_STARTINDENT; pf2.dxStartIndent = lStartIndent; SetParaFormat(pf2); } void CRichEditEx::SetColor(COLORREF color) { CHARFORMAT cf; cf.cbSize = sizeof(CHARFORMAT); cf.dwMask = CFM_COLOR; GetSelectionCharFormat(cf); cf.crTextColor = color; if( cf.dwEffects & CFE_AUTOCOLOR ) { cf.dwEffects ^= CFE_AUTOCOLOR; } SetSelectionCharFormat(cf); } void CRichEditEx::SetJustify(void) { PARAFORMAT pf; pf.cbSize = sizeof(PARAFORMAT); pf.dwMask = PFM_ALIGNMENT; pf.wAlignment = PFA_JUSTIFY; SetParaFormat(pf); // Set the paragraph. } void CRichEditEx::SetWordWrap(const bool bOn, const int iLineWidth) { if( bOn ) SetTargetDevice(NULL, iLineWidth); else { if( 0 == iLineWidth ) SetTargetDevice(NULL, 1); else SetTargetDevice(NULL, iLineWidth); } } void CRichEditEx::InsertGraph(HBITMAP hBitmap) { //CImageDataObject::InsertBitmap(this->.GetIRichEditOle(), 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 ); delete pDataSource; */ 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 ///获取RichEdit的OLEClientSite LPOLECLIENTSITE lpClientSite; this->GetIRichEditOle()->GetClientSite( &lpClientSite ); ///创建OLE对象 IOleObject *pOleObject; sc = OleCreateStaticFromData(lpDataObject,IID_IOleObject,OLERENDER_FORMAT, &fm,lpClientSite,pStorage,(void **)&pOleObject);//OleCreateStaticFromData 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 ); //* if(pDataSource) delete pDataSource; if(pOleObject) pOleObject->Release(); if(lpLockBytes) lpLockBytes->Release(); if(lpClientSite) lpClientSite->Release(); if (pStorage) pStorage->Release(); //*/ } void CRichEditEx::InsertGraph(CString strPicPath) { /* LPLOCKBYTES lpLockBytes = NULL; SCODE sc; HRESULT hr; //print to RichEdit' s IClientSite LPOLECLIENTSITE m_lpClientSite; //A smart point to IAnimator ImageOleLib::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 this->GetIRichEditOle()->GetClientSite(&m_lpClientSite); ASSERT(m_lpClientSite != NULL); try { //Initlize COM interface hr = ::CoInitialize(NULL) ;//( NULL, COINIT_APARTMENTTHREADED ); 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.CreateInstance(ImageOleLib::CLSID_GifAnimator); 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); if( FAILED(hr) ) _com_issue_error(hr); TRACE0( m_lpAnimator->GetFilePath() ); //get the IOleObject hr = m_lpAnimator.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 = ( DWORD )m_lpAnimator; //Save Animator //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; this->GetIRichEditOle()->InsertObject(&reobject); ::SendMessage(hWndRT, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0); VARIANT_BOOL ret; //do frame changing ret = m_lpAnimator->TriggerFrameChange(); //show it m_lpObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, m_lpClientSite, 0, hWndRT, NULL); m_lpObject->DoVerb(OLEIVERB_SHOW, NULL, m_lpClientSite, 0, hWndRT, NULL); //redraw the window to show animation this->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(); } */ }