479 lines
15 KiB
C++
479 lines
15 KiB
C++
// RichEditEx.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
//#include "Exppp.h"
|
|
#include "RichEditEx.h"
|
|
#include <Richole.h>
|
|
#include <afxole.h>
|
|
|
|
//使用了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();
|
|
}
|
|
*/
|
|
}
|