📄 faceedit.cpp
字号:
LONG lindex; // (-1) 在数据通过页面边界分割的时候使用
DWORD tymed; // 用于数据传输的存储媒体(HGLOBAL,IStream)
} FORMATETC;
FORMATETC结构的成员如下描述:
cfFormat:粘贴板格式,用来表示FORMATETC结构。可以是内建的格式(例如:CF_TEXT或CF_BITMAP)或者用RegisterClipboardFormat注册的自定义格式。
Ptd:指向DVTARGETDEVICE结构,提供已经rendered数据的设备信息。正常的粘贴板操作和拖放操作都是NULL。
dwAspect:描述用户怎么样render数据的大量细节。通常这个是DVASPECT_CONTECT,表示全内容,但也可以描述较少的信息,例如:图标。
Lindex:仅仅在当数据通过页面边界被分割的时候使用,它不用于简单的OLE传输,因此该值几乎总是-1。
Typemed:这是一个有趣的成员;因为其描述了用于存储数据的存储媒体类型。该成员名字自词组“Type of Medium”;该值在window.h中定义的TYMED_XXX等值。
因此有了这个数据结构,OLE已经提供了一个描述消费者什么样的数据已经怎么样render这个数据。
存储OLE数据
结构体STGMEDIUM(STORAGE MEDIUM的缩写)提供一个用来存储数据的容器,因此叫存储媒体:
typedef struct
{
DWORD tymed;
union
{
HBITMAP hBitmap;
HMETAFILEPICT hMetaFilePict;
HENHMETAFILE hEnhMetaFile;
HGLOBAL hGlobal;
LPWSTR lpszFileName;
IStream *pstm;
IStorage *pstg;
};
IUnknown *pUnkForRelease;
} STGMEDIUM;
这个结构定义看起来比较复杂,但是有用的仅仅三个成员,因为未命名联合合并了所有内容作为一个实体共享同样的存储空间。
1. tymed:这个成员必须和FORMATETC结构相同,这个成员指定已经存储的媒体类型,例如,全局数据(TYMED_HGLOBAL),IStream(TYPED_ISTREAM)等等。相应的联合中的元素是数据的句柄。
2. hBitmap/hGlobal等:实际的数据,仅仅他们中的一个是有效的,这依赖于tymed的值。
3. pUnkForRelease:一个可选的指针,指向IUnknown接口,数据的接收方应该调用其Release方法。当这个字段是NULL时,接收方有责任释放内存句柄。ReleaseStgMedium API调用在这里非常有用,它负责释放STGMEDIUMS的数据内容,因此实际上我们不需要做什么。
STGMEDIUM结构是传统的windows HGLOBAL内存句柄的扩展,同时支持HGLOBAL(且一直是最常用的),同时支持许多其他的类型,最有用的是IStream和IStorage通用COM接口。
总之,结构体FORMATETC和STGMEDIUM一起用来描述和存储OLE数据实体的。FORMATETC通常用来从IDataObject请求指定类型的数据,同时STGMEDIUM结构用来接收和保存请求的数据。
*/
void InsertBitmap(CRichEditCtrl *pRichEdit, HBITMAP hBitmap) //底层的一个InsertBitmap
{
STGMEDIUM stgm; //提供用于数据传输操作的通用化全局内存句柄
stgm.tymed = TYMED_GDI; // Storage medium = HBITMAP handle
stgm.hBitmap = hBitmap;
stgm.pUnkForRelease = NULL; // Use ReleaseStgMedium
/* WCHAR wchar[10] = {'1','1','.','g','i','f'};
STGMEDIUM stgm;
stgm.tymed = TYMED_MFPICT;
// stgm.lpszFileName=filename;
stgm.lpszFileName = wchar;
// stgm.hGlobal = hMetaPict.m_pPicture;
// stgm.hGlobal = hMetaPict;
stgm.pUnkForRelease = NULL;*/
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;
/*FORMATETC fm;
fm.cfFormat = TYMED_MFPICT;
fm.ptd = NULL;
fm.dwAspect = DVASPECT_CONTENT;
fm.lindex = -1;
fm.tymed = TYMED_ISTREAM;*/
/*
{ TYMED_HGLOBAL = 1,
TYMED_FILE = 2,
TYMED_ISTREAM = 4,
TYMED_ISTORAGE = 8,
TYMED_GDI = 16,
TYMED_MFPICT = 32,
TYMED_ENHMF = 64,
TYMED_NULL = 0
*/
//创建输入数据源
/* FORMATETC fmtetc;
STGMEDIUM stg;
fmtetc.cfFormat = m_cfImageFile;
fmtetc.dwAspect = DVASPECT_CONTENT;
fmtetc.ptd = NULL;
fmtetc.tymed = TYMED_ISTREAM;
fmtetc.lindex = -1;
WCHAR filename[256];
MultiByteToWideChar(CP_ACP,
MB_PRECOMPOSED,
(LPCSTR)m_szFileName,
m_szFileName.GetLength(),
(LPWSTR)filename,
sizeof(filename));
stg.tymed=TYMED_ISTREAM;
stg.lpszFileName=filename;//lpszFileName;
COleDataSource* pSource=new COleDataSource();
pSource->CacheData(m_cfImageFile, &stg, &fmtetc); */
IStorage *pStorage; //IStorage是结构或存储的文件接口。通过IStorage可以操作结构化存储的文件。
//分配内存
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);
//设置Ole数据
COleDataSource *pDataSource = new COleDataSource;
pDataSource->CacheData(CF_BITMAP, &stgm);
LPDATAOBJECT lpDataObject = (LPDATAOBJECT)pDataSource->GetInterface(&IID_IDataObject);//OleGetClipboard(&lpDataObject);
//获取RichEdit的OLEClientSite
LPOLECLIENTSITE lpClientSite;
pRichEdit->GetIRichEditOle()->GetClientSite( &lpClientSite );
//创建OLE对象 ???如何设置lpDataObject 和 fm ?????? pStorage ?????
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 = pRichEdit->GetIRichEditOle()->InsertObject( &reobject );
delete pDataSource;
}
void CFaceEdit::InsertFace(CString strPicPath)
{
}
void CFaceEdit::SetFaceToText()
{
CString str;
GetWindowText(str);
int count = vecFace.size();
for(int i = 0;i < count;i ++)
{
str.Insert(vecFace[i].nPos,m_pSymbol[vecFace[i].nFaceIndex]);
}
}
void CFaceEdit::ClearFace()
{
vecFace.clear();
}
/*LPPICTURE gpPicture;
// This function loads a file into an IStream.
void LoadPictureFile(LPCTSTR szFile)
{
// open file
HANDLE hFile = CreateFile(szFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
_ASSERTE(INVALID_HANDLE_VALUE != hFile);
// get file size
DWORD dwFileSize = GetFileSize(hFile, NULL);
_ASSERTE(-1 != dwFileSize);
LPVOID pvData = NULL;
// alloc memory based on file size
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);
_ASSERTE(NULL != hGlobal);
pvData = GlobalLock(hGlobal);
_ASSERTE(NULL != pvData);
DWORD dwBytesRead = 0;
// read file and store in global memory
BOOL bRead = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL);
_ASSERTE(FALSE != bRead);
GlobalUnlock(hGlobal);
CloseHandle(hFile);
LPSTREAM pstm = NULL;
// create IStream* from global memory
HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm);
_ASSERTE(SUCCEEDED(hr) && pstm);
// Create IPicture from image file
if (gpPicture)
gpPicture->Release();
hr = ::OleLoadPicture(pstm, dwFileSize, FALSE, IID_IPicture, (LPVOID *)&gpPicture);
_ASSERTE(SUCCEEDED(hr) && gpPicture);
pstm->Release();
InvalidateRect(ghWnd, NULL, TRUE);
}
。。。。。。
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
if (gpPicture)
{
// get width and height of picture
long hmWidth;
long hmHeight;
gpPicture->get_Width(&hmWidth);
gpPicture->get_Height(&hmHeight);
// convert himetric to pixels
int nWidth = MulDiv(hmWidth, GetDeviceCaps(hdc, LOGPIXELSX), HIMETRIC_INCH);
int nHeight = MulDiv(hmHeight, GetDeviceCaps(hdc, LOGPIXELSY), HIMETRIC_INCH);
RECT rc;
GetClientRect(hWnd, &rc);
// display picture using IPicture::Render
gpPicture->Render(hdc, 0, 0, nWidth, nHeight, 0, hmHeight, hmWidth, -hmHeight, &rc);
}
EndPaint(hWnd, &ps);
break;*/
void CFaceEdit::InsertBitmap(CString szFileName)
{
USES_CONVERSION;
LPLOCKBYTES m_lpLockBytes = NULL;
IStorage *m_lpStorage;
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);
}
IOleObject *m_lpObject;
sc = ::OleCreateFromFile(CLSID_NULL, T2COLE(szFileName),IID_IUnknown, OLERENDER_DRAW, NULL, NULL,
m_lpStorage, (void **)&m_lpObject);
if ( sc != S_OK )
{
return;
}
/* if (m_lpObject != NULL)
{
LPUNKNOWN lpUnk = m_lpObject;
m_lpObject = GetInterface(lpUnk, IOleObject);
lpUnk->Release();
if (m_lpObject == NULL)
AfxThrowOleException(E_OUTOFMEMORY);
}
m_lpViewObject = GetInterface(m_lpObject, IViewObject2);
if (m_lpViewObject == NULL)
return;
LPADVISESINK lpAdviseSink = (LPADVISESINK)GetInterface(&IID_IAdviseSink);
VERIFY(m_lpViewObject->SetAdvise(DVASPECT_CONTENT, 0, lpAdviseSink) == S_OK);*/
m_lpObject->SetHostNames(T2COLE(AfxGetAppName()),T2COLE(_T("Test")));
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 CFaceEdit::InsertGif(CString filename)
{
/*IRichEditOle ReOle;
IOleClientSite OleSite;
IStorage Storage;
ILockBytes LockBytes;
IOleObject OleObject;
REOBJECT ReObj;
IGifAnimator Animator;
ReOle = GetRichEditOle(hRichEdit);
ReOle.GetClientSite(OleSite);
OleCheck(CreateILockBytesOnHGlobal(0, True, LockBytes));
OleCheck(StgCreateDocfileOnILockBytes(LockBytes,
STGM_SHARE_EXCLUSIVE || STGM_CREATE || STGM_READWRITE, 0, Storage));
Animator = IUnknown(CreateComObject(CLASS_GifAnimator));
Animator.LoadFromFile(PWideChar(WideString(FileName)));
OleCheck(Animator.QueryInterface(IID_IOleObject, OleObject));
OleCheck(OleSetContainedObject(OleObject, True));
FillChar(ReObj, Sizeof(ReObj), 0);
ReObj.cbStruct := Sizeof(ReObj);
OleCheck(OleObject.GetUserClassID(ReObj.clsid));
ReObj.cp := REO_CP_SELECTION;
ReObj.dvaspect := DVASPECT_CONTENT;
ReObj.dwFlags := REO_STATIC or REO_BELOWBASELINE;
ReObj.dwUser := 0;
ReObj.poleobj := OleObject;
ReObj.polesite := OleSite;
ReObj.pstg := Storage;
ReObj.sizel.cx := 0;
ReObj.sizel.cy := 0;
ReOle.InsertObject(ReObj);*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -