; .NET RichTextBox, , COM- IRichEditOleCallback.
, ATL ++ ( , , , COM- Plain Ol , ):
#include <windows.h>
#include <Richole.h>
#include <atlbase.h>
#include <atlcom.h>
#include <atlcomcli.h>
#include <string>
struct RattyRichEditOleCallbackImpl: public CComObjectRoot, public IRichEditOleCallback
{
HWND* hRichEdit;
RattyRichEditOleCallbackImpl(): hRichEdit(NULL) {}
HRESULT SetRichEditCtl(HWND *hCtl)
{
hRichEdit = hCtl;
return S_OK;
}
HRESULT QueryAcceptData(LPDATAOBJECT lpdataobj, CLIPFORMAT* lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict)
{
if (*lpcfFormat == CF_DIB || *lpcfFormat == CF_DIBV5
|| *lpcfFormat == CF_BITMAP || *lpcfFormat == CF_TIFF
|| *lpcfFormat == CF_ENHMETAFILE || *lpcfFormat == CF_METAFILEPICT
|| *lpcfFormat == CF_PALETTE || *lpcfFormat == CF_DSPBITMAP
|| *lpcfFormat == CF_DSPMETAFILEPICT || *lpcfFormat == CF_DSPENHMETAFILE
|| *lpcfFormat >= CF_GDIOBJECTFIRST || *lpcfFormat <= CF_GDIOBJECTLAST)
{
return E_NOTIMPL;
}
else
{
*lpcfFormat = CF_UNICODETEXT;
if (fReally)
{
FORMATETC fmt = {*lpcfFormat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
STGMEDIUM stg;
HRESULT res = E_UNEXPECTED;
if (hRichEdit && (res = lpdataobj->GetData(fmt, stg)) == S_OK)
{
WCHAR* pText = GlobalLock(stg.hGlobal);
if (!pText)
{
ReleaseStgMedium(stg);
return res;
}
std::wstring text(pText);
DWORD cursorPos, selPos;
SendMessageW(hRichEdit, EM_GETSEL, &cursorPos, &selPos);
if (cursorPos == selPos)
{
SendMessageW(hRichEdit, EM_SETSEL, cursorPos, cursorPos + 1);
WCHAR buffer[2];
TEXTRANGEW tr = {{cursorPos, cursorPos + 1}, buffer};
SendMessageW(hRichEdit, EM_GETTEXTRANGE, 0, &tr);
text.append(buffer[0]);
}
CHARFORMAT2 cf;
cf.cbSize = sizeof(CHARFORMAT2);
SendMessageW(hRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, &cf);
SendMessageW(hRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, &cf);
SendMessageW(hRichEdit, EM_REPLACESEL, TRUE, text.c_str());
GlobalUnlock(stg.hGlobal);
ReleaseStgMedium(stg);
res = S_FALSE;
}
return res;
}
else
{
return S_OK;
}
}
}
};
typedef CComObject<RattyRichEditOleCallbackImpl> RattyRichEditOleCallback;
inline void AttachRattyCallbackToRichEdit(HWND *hRichEdit)
{
RattyRichEditOleCallback* pCb;
if (RattyRichEditOleCallback::CreateInstance(&pCb) == S_OK)
{
CComPtr cb(pCb);
cb->SetRichEditCtl(hRichEdit);
SendMessage(hRichEdit, EM_SETOLECALLBACK, 0, cb);
}
}