|
|
// SSmileyCtrl.cpp : Implementation of SSmileyCtrl
|
|
|
#include <Windows.h>
|
|
|
#include "../controls.extend/smiley/SSmileyCtrl.h"
|
|
|
|
|
|
#include <TOM.h>
|
|
|
#include <richedit.h>
|
|
|
|
|
|
#include <atlbase.h>
|
|
|
#include <atlcom.h>
|
|
|
#include <atlwin.h>
|
|
|
#include <atltypes.h>
|
|
|
#include <atlctl.h>
|
|
|
#include <atlhost.h>
|
|
|
|
|
|
const GUID CLSID_SSmileyCtrl =
|
|
|
{0xd29e0bde,0xcfda,0x4b93,{0x92,0x9a,0x87,0x7a,0xb4,0x55,0x7b,0xd9}};
|
|
|
|
|
|
|
|
|
DWORD _GenerateID()
|
|
|
{
|
|
|
static DWORD s_id=1;
|
|
|
return s_id++;
|
|
|
}
|
|
|
|
|
|
// CCSmiley
|
|
|
|
|
|
class ATL_NO_VTABLE SSmileyCtrl :
|
|
|
public CComObjectRootEx<CComSingleThreadModel>,
|
|
|
public CComControl<SSmileyCtrl>,
|
|
|
public IOleObjectImpl<SSmileyCtrl>,
|
|
|
public IOleInPlaceObjectWindowlessImpl<SSmileyCtrl>,
|
|
|
public IViewObjectExImpl<SSmileyCtrl>,
|
|
|
public IPersistStreamInitImpl<SSmileyCtrl>,
|
|
|
public IPersistStorageImpl<SSmileyCtrl>,
|
|
|
public IOleControlImpl<SSmileyCtrl>,
|
|
|
public ITimerHandler,
|
|
|
public ISmileyCtrl
|
|
|
{
|
|
|
public:
|
|
|
|
|
|
DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE |
|
|
|
OLEMISC_CANTLINKINSIDE |
|
|
|
OLEMISC_INSIDEOUT |
|
|
|
OLEMISC_ACTIVATEWHENVISIBLE |
|
|
|
OLEMISC_SETCLIENTSITEFIRST
|
|
|
)
|
|
|
|
|
|
BEGIN_COM_MAP(SSmileyCtrl)
|
|
|
COM_INTERFACE_ENTRY(ITimerHandler)
|
|
|
COM_INTERFACE_ENTRY(ISmileyCtrl)
|
|
|
COM_INTERFACE_ENTRY(IOleControl)
|
|
|
COM_INTERFACE_ENTRY(IOleObject)
|
|
|
COM_INTERFACE_ENTRY(IViewObject)
|
|
|
COM_INTERFACE_ENTRY(IViewObject2)
|
|
|
COM_INTERFACE_ENTRY(IViewObjectEx)
|
|
|
COM_INTERFACE_ENTRY(IPersistStreamInit)
|
|
|
COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
|
|
|
COM_INTERFACE_ENTRY(IPersistStorage)
|
|
|
END_COM_MAP()
|
|
|
|
|
|
BEGIN_PROP_MAP(SSmileyCtrl)
|
|
|
END_PROP_MAP()
|
|
|
|
|
|
BEGIN_MSG_MAP(SSmileyCtrl)
|
|
|
CHAIN_MSG_MAP(CComControl<SSmileyCtrl>)
|
|
|
DEFAULT_REFLECTION_HANDLER()
|
|
|
END_MSG_MAP()
|
|
|
|
|
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
|
|
|
|
|
public:
|
|
|
SSmileyCtrl();
|
|
|
~SSmileyCtrl();
|
|
|
|
|
|
static CLSID GetObjectCLSID(){
|
|
|
return CLSID_SSmileyCtrl;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public://ISoSmileyCtrl
|
|
|
STDMETHOD(Insert2Richedit)(IRichEditOle * ole);
|
|
|
STDMETHOD(SetSource)(ISmileySource * pSource);
|
|
|
STDMETHOD(GetSource)(ISmileySource ** ppSource);
|
|
|
|
|
|
public://IOleObject
|
|
|
STDMETHOD(SetClientSite)(IOleClientSite *pClientSite);
|
|
|
STDMETHOD(GetMiscStatus)(DWORD dwAspect, DWORD *pdwStatus);
|
|
|
|
|
|
public://IPersistStreamInitImpl
|
|
|
#if _MSC_VER>1400
|
|
|
HRESULT IPersistStreamInit_Load(LPSTREAM pStm, const ATL_PROPMAP_ENTRY* pMap);
|
|
|
HRESULT IPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty, const ATL_PROPMAP_ENTRY* pMap);
|
|
|
#else
|
|
|
HRESULT IPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap);
|
|
|
HRESULT IPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty, ATL_PROPMAP_ENTRY* pMap);
|
|
|
#endif
|
|
|
HRESULT FireViewChange();
|
|
|
HRESULT OnDraw(ATL_DRAWINFO& di);
|
|
|
public://IPersistStorage
|
|
|
STDMETHOD(Load)(IStorage* pStorage);//<EFBFBD><EFBFBD><EFBFBD><EFBFBD>IPersistStorage::Load<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD>д<EFBFBD>뼸<EFBFBD><EFBFBD><EFBFBD><EFBFBD>־λ
|
|
|
|
|
|
public://ITimerHander
|
|
|
STDMETHOD(OnTimer)(HDC hdc);
|
|
|
STDMETHOD(Clear)();;
|
|
|
STDMETHOD(GetRect)(LPRECT pRect){memcpy(pRect,&m_rcPos,sizeof(RECT));return S_OK;};
|
|
|
|
|
|
private:
|
|
|
void UpdateSmiley(HDC hdc);
|
|
|
void UpdateSmileyFlag();
|
|
|
DWORD GetSmileyFlag(IRichEditOle *ole,int iFirst,int iLast);
|
|
|
|
|
|
CComPtr<ISmileyHost> m_pSmileyHost;
|
|
|
CComPtr<ISmileySource> m_pSmileySource;
|
|
|
int m_iFrameIndex;
|
|
|
DWORD m_dwID;
|
|
|
|
|
|
DWORD m_dwDrawFlag;
|
|
|
};
|
|
|
|
|
|
|
|
|
SSmileyCtrl::SSmileyCtrl():m_iFrameIndex(0),m_dwDrawFlag(0)
|
|
|
{
|
|
|
m_dwID = _GenerateID();
|
|
|
memset(&m_rcPos,0,sizeof(RECT));
|
|
|
m_bRecomposeOnResize=1;
|
|
|
}
|
|
|
|
|
|
SSmileyCtrl::~SSmileyCtrl()
|
|
|
{
|
|
|
if(m_pSmileyHost)
|
|
|
{//<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD>
|
|
|
m_pSmileyHost->KillTimer(this);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
STDMETHODIMP SSmileyCtrl::Insert2Richedit(IRichEditOle * ole)
|
|
|
{
|
|
|
if(!m_pSmileySource) return E_FAIL;
|
|
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
//insert this to host
|
|
|
CComPtr<IOleObject> pOleObject;
|
|
|
CComPtr<IOleClientSite> pClientSite;
|
|
|
|
|
|
// Get site
|
|
|
ole->GetClientSite(&pClientSite);
|
|
|
ATLASSERT(pClientSite != NULL);
|
|
|
|
|
|
CComPtr<IRichEditOleCallback> pCallback;
|
|
|
hr=ole->QueryInterface(IID_IRichEditOleCallback,(void**)&pCallback);
|
|
|
if(!SUCCEEDED(hr)) return E_FAIL;
|
|
|
|
|
|
//get the IOleObject
|
|
|
hr = _InternalQueryInterface(IID_IOleObject, (void**)&pOleObject);
|
|
|
if (FAILED(hr))
|
|
|
{
|
|
|
return E_FAIL;
|
|
|
}
|
|
|
|
|
|
//to insert into richedit, you need a struct of REOBJECT
|
|
|
REOBJECT reobject;
|
|
|
ZeroMemory(&reobject, sizeof(REOBJECT));
|
|
|
|
|
|
reobject.cbStruct = sizeof(REOBJECT);
|
|
|
|
|
|
CLSID clsid;
|
|
|
pOleObject->GetUserClassID(&clsid);
|
|
|
|
|
|
//get storage
|
|
|
pCallback->GetNewStorage(&reobject.pstg);
|
|
|
|
|
|
//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;
|
|
|
reobject.dwUser = (DWORD)m_dwID;
|
|
|
//the very object
|
|
|
reobject.poleobj = pOleObject;
|
|
|
//client site contain the object
|
|
|
reobject.polesite = pClientSite;
|
|
|
|
|
|
SIZEL sizel={0};
|
|
|
reobject.sizel = sizel;
|
|
|
|
|
|
hr = pOleObject->SetClientSite(pClientSite);
|
|
|
|
|
|
if(SUCCEEDED(hr))
|
|
|
{
|
|
|
hr = ole->InsertObject(&reobject);
|
|
|
|
|
|
FireViewChange();
|
|
|
}
|
|
|
|
|
|
if(reobject.pstg)
|
|
|
{
|
|
|
reobject.pstg->Release();
|
|
|
}
|
|
|
|
|
|
return hr;
|
|
|
}
|
|
|
|
|
|
|
|
|
STDMETHODIMP SSmileyCtrl::SetSource(ISmileySource * pSource)
|
|
|
{
|
|
|
m_pSmileySource = pSource;
|
|
|
if(m_pSmileySource)
|
|
|
{
|
|
|
//<EFBFBD><EFBFBD><EFBFBD>±<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
|
|
|
SIZE sz;
|
|
|
m_pSmileySource->GetSize(&sz);
|
|
|
|
|
|
HDC hDC = ::GetDC(NULL);
|
|
|
m_sizeExtent.cx = ::MulDiv(sz.cx, 2540, GetDeviceCaps(hDC, LOGPIXELSX));
|
|
|
m_sizeExtent.cy = ::MulDiv(sz.cy, 2540, GetDeviceCaps(hDC, LOGPIXELSY));
|
|
|
::ReleaseDC(NULL, hDC);
|
|
|
}
|
|
|
|
|
|
return S_OK;
|
|
|
}
|
|
|
|
|
|
STDMETHODIMP SSmileyCtrl::GetSource(ISmileySource ** ppSource)
|
|
|
{
|
|
|
if(! m_pSmileySource) return E_FAIL;
|
|
|
*ppSource = m_pSmileySource;
|
|
|
(*ppSource)->AddRef();
|
|
|
return S_OK;
|
|
|
}
|
|
|
|
|
|
STDMETHODIMP SSmileyCtrl::OnTimer(HDC hdc)
|
|
|
{
|
|
|
int cFrame = 1;
|
|
|
m_pSmileySource->GetFrameCount(&cFrame);
|
|
|
m_iFrameIndex++;
|
|
|
m_iFrameIndex %= cFrame;
|
|
|
UpdateSmiley(hdc);
|
|
|
return S_OK;
|
|
|
}
|
|
|
|
|
|
#if _MSC_VER>1400
|
|
|
HRESULT SSmileyCtrl::IPersistStreamInit_Load(LPSTREAM pStm, const ATL_PROPMAP_ENTRY* pMap)
|
|
|
#else
|
|
|
HRESULT SSmileyCtrl::IPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap)
|
|
|
#endif
|
|
|
{
|
|
|
ATLASSERT(!m_pSmileySource);
|
|
|
ATLASSERT(m_pSmileyHost);
|
|
|
CComPtr<ISmileySource> pSource;
|
|
|
HRESULT hr =m_pSmileyHost->CreateSource(&pSource);
|
|
|
if(!SUCCEEDED(hr)) return hr;
|
|
|
hr = pSource->Stream_Load(pStm);
|
|
|
if(!SUCCEEDED(hr)) return hr;
|
|
|
SetSource(pSource);
|
|
|
|
|
|
hr = IPersistStreamInitImpl<SSmileyCtrl>::IPersistStreamInit_Load( pStm, pMap);
|
|
|
|
|
|
if(!SUCCEEDED(hr)) return hr;
|
|
|
FireViewChange();
|
|
|
return hr;
|
|
|
}
|
|
|
|
|
|
#if _MSC_VER>1400
|
|
|
HRESULT SSmileyCtrl::IPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty, const ATL_PROPMAP_ENTRY* pMap)
|
|
|
#else
|
|
|
HRESULT SSmileyCtrl::IPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty, ATL_PROPMAP_ENTRY* pMap)
|
|
|
#endif
|
|
|
{
|
|
|
if(!m_pSmileySource) return E_FAIL;
|
|
|
HRESULT hr = m_pSmileySource->Stream_Save(pStm);
|
|
|
if(!SUCCEEDED(hr)) return hr;
|
|
|
return IPersistStreamInitImpl<SSmileyCtrl>::IPersistStreamInit_Save( pStm, fClearDirty, pMap);
|
|
|
}
|
|
|
|
|
|
HRESULT SSmileyCtrl::FireViewChange()
|
|
|
{
|
|
|
if (m_bInPlaceActive)
|
|
|
{
|
|
|
// Active
|
|
|
if (m_hWndCD != NULL)
|
|
|
::InvalidateRect(m_hWndCD, NULL, TRUE); // Window based
|
|
|
else if (m_bWndLess && m_spInPlaceSite != NULL)
|
|
|
m_spInPlaceSite->InvalidateRect(NULL, TRUE); // Windowless
|
|
|
}
|
|
|
else if (!m_pSmileyHost)
|
|
|
{
|
|
|
SendOnViewChange(DVASPECT_CONTENT);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// UpdateSmiley(NULL);
|
|
|
}
|
|
|
return S_OK;
|
|
|
}
|
|
|
|
|
|
HRESULT SSmileyCtrl::OnDraw(ATL_DRAWINFO& di)
|
|
|
{
|
|
|
if(!m_pSmileySource) return E_FAIL;
|
|
|
RECT rc={di.prcBounds->left,di.prcBounds->top,di.prcBounds->right,di.prcBounds->bottom};
|
|
|
m_pSmileySource->Draw(di.hdcDraw,&rc,m_iFrameIndex);
|
|
|
if(!di.bZoomed)
|
|
|
{//<EFBFBD><EFBFBD>copyʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>bZoomed<EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><EFBFBD>ηŴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
m_rcPos = rc;//cache pos, position will be updated in response to EN_UPDATE message come from it's host
|
|
|
}
|
|
|
|
|
|
int nDelay=0;
|
|
|
HRESULT hr = m_pSmileySource->GetFrameDelay(m_iFrameIndex,&nDelay);
|
|
|
if(SUCCEEDED(hr) && m_pSmileyHost)
|
|
|
{
|
|
|
m_pSmileyHost->SetTimer(this,nDelay);
|
|
|
}
|
|
|
return S_OK;
|
|
|
}
|
|
|
|
|
|
|
|
|
void SSmileyCtrl::UpdateSmiley(HDC hdc)
|
|
|
{
|
|
|
if(!m_pSmileyHost) return ;
|
|
|
if(::IsRectEmpty(&m_rcPos)) return;
|
|
|
|
|
|
if(!hdc) return;
|
|
|
|
|
|
UpdateSmileyFlag();
|
|
|
|
|
|
m_pSmileySource->Draw(hdc,&m_rcPos,m_iFrameIndex);
|
|
|
|
|
|
if (m_dwDrawFlag == REO_INVERTEDSELECT)
|
|
|
{
|
|
|
//Invert entire object
|
|
|
InvertRect(hdc, &m_rcPos);
|
|
|
}
|
|
|
else if(m_dwDrawFlag == REO_SELECTED)
|
|
|
{
|
|
|
// Just the border, so use a null brush
|
|
|
SaveDC(hdc);
|
|
|
SetROP2(hdc, R2_NOT);
|
|
|
SelectObject(hdc, GetStockObject(NULL_BRUSH));
|
|
|
Rectangle(hdc, m_rcPos.left, m_rcPos.top, m_rcPos.right, m_rcPos.bottom);
|
|
|
RestoreDC(hdc, -1);
|
|
|
}
|
|
|
|
|
|
int nDelay=0;
|
|
|
HRESULT hr = m_pSmileySource->GetFrameDelay(m_iFrameIndex,&nDelay);
|
|
|
if(SUCCEEDED(hr) && m_pSmileyHost)
|
|
|
{
|
|
|
m_pSmileyHost->SetTimer(this,nDelay);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
HRESULT SSmileyCtrl::Load( IStorage* pStorage )
|
|
|
{
|
|
|
//<EFBFBD><EFBFBD>RichEditFlags<EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD>3<EFBFBD><EFBFBD>REOBJECT<EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Richedit20<EFBFBD><EFBFBD>winceԴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɲ<EFBFBD><EFBFBD><EFBFBD>richeditǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"RichEditFlags"<EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>3<EFBFBD><EFBFBD><EFBFBD><EFBFBD>־λ
|
|
|
CComPtr<IStream> spStream;
|
|
|
static LPCOLESTR vszRichEditFlags = OLESTR("RichEditFlags");
|
|
|
HRESULT hr = pStorage->CreateStream(vszRichEditFlags,
|
|
|
STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
|
|
|
0, 0, &spStream);
|
|
|
if (FAILED(hr)) return hr;
|
|
|
DWORD dwFlag=REO_BELOWBASELINE,dwUser=m_dwID,dwAspect=DVASPECT_CONTENT;
|
|
|
spStream->Write(&dwFlag,sizeof(dwFlag),NULL);
|
|
|
spStream->Write(&dwUser,sizeof(dwUser),NULL);
|
|
|
spStream->Write(&dwAspect,sizeof(dwAspect),NULL);
|
|
|
|
|
|
return IPersistStorageImpl<SSmileyCtrl>::Load(pStorage);
|
|
|
}
|
|
|
|
|
|
STDMETHODIMP SSmileyCtrl::GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus)
|
|
|
{
|
|
|
(dwAspect);
|
|
|
*pdwStatus = OLEMISC_RECOMPOSEONRESIZE |
|
|
|
OLEMISC_CANTLINKINSIDE |
|
|
|
OLEMISC_INSIDEOUT |
|
|
|
OLEMISC_ACTIVATEWHENVISIBLE |
|
|
|
OLEMISC_SETCLIENTSITEFIRST;
|
|
|
return S_OK;
|
|
|
}
|
|
|
|
|
|
STDMETHODIMP SSmileyCtrl::SetClientSite(IOleClientSite *pClientSite)
|
|
|
{
|
|
|
if(pClientSite)
|
|
|
{
|
|
|
CComPtr<IRichEditOleCallback> pCallback;
|
|
|
HRESULT hr=pClientSite->QueryInterface(IID_IRichEditOleCallback,(void**)&pCallback);
|
|
|
if(FAILED(hr)) return E_FAIL;
|
|
|
|
|
|
//<EFBFBD><EFBFBD>callback<EFBFBD>л<EFBFBD>ȡhost
|
|
|
hr = pCallback->QueryInterface(__uuidof(ISmileyHost),(LPVOID*)&m_pSmileyHost);
|
|
|
if(FAILED(hr)) return E_FAIL;
|
|
|
}
|
|
|
|
|
|
return __super::SetClientSite(pClientSite);
|
|
|
}
|
|
|
|
|
|
|
|
|
LONG GetOleCP(IRichEditOle *pOle, int iOle)
|
|
|
{
|
|
|
REOBJECT reobj={0};
|
|
|
reobj.cbStruct=sizeof(REOBJECT);
|
|
|
pOle->GetObject(iOle,&reobj,REO_GETOBJ_NO_INTERFACES);
|
|
|
return reobj.cp;
|
|
|
}
|
|
|
|
|
|
//find first Ole Object in char range of [cpMin,cpMax)
|
|
|
int FindFirstOleInrange(IRichEditOle *pOle, int iBegin,int iEnd,int cpMin,int cpMax)
|
|
|
{
|
|
|
if(iBegin==iEnd) return -1;
|
|
|
|
|
|
int iMid = (iBegin + iEnd)/2;
|
|
|
|
|
|
LONG cp = GetOleCP(pOle,iMid);
|
|
|
|
|
|
if(cp < cpMin)
|
|
|
{
|
|
|
return FindFirstOleInrange(pOle,iMid+1,iEnd,cpMin,cpMax);
|
|
|
}else if(cp >= cpMax)
|
|
|
{
|
|
|
return FindFirstOleInrange(pOle,iBegin,iMid,cpMin,cpMax);
|
|
|
}else
|
|
|
{
|
|
|
int iRet = iMid;
|
|
|
while(iRet>iBegin)
|
|
|
{
|
|
|
cp = GetOleCP(pOle,iRet-1);
|
|
|
if(cp<cpMin) break;
|
|
|
iRet --;
|
|
|
}
|
|
|
return iRet;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//find Last Ole Object in char range of [cpMin,cpMax)
|
|
|
int FindLastOleInrange(IRichEditOle *pOle, int iBegin,int iEnd,int cpMin,int cpMax)
|
|
|
{
|
|
|
if(iBegin==iEnd) return -1;
|
|
|
|
|
|
int iMid = (iBegin + iEnd)/2;
|
|
|
|
|
|
LONG cp = GetOleCP(pOle,iMid);
|
|
|
|
|
|
if(cp < cpMin)
|
|
|
{
|
|
|
return FindLastOleInrange(pOle,iMid+1,iEnd,cpMin,cpMax);
|
|
|
}else if(cp >= cpMax)
|
|
|
{
|
|
|
return FindLastOleInrange(pOle,iBegin,iMid,cpMin,cpMax);
|
|
|
}else
|
|
|
{
|
|
|
int iRet = iMid;
|
|
|
while(iRet<(iEnd-1))
|
|
|
{
|
|
|
cp = GetOleCP(pOle,iRet+1);
|
|
|
if(cp>=cpMax) break;
|
|
|
iRet ++;
|
|
|
}
|
|
|
return iRet;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
//<EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><EFBFBD><EFBFBD>״̬
|
|
|
DWORD SSmileyCtrl::GetSmileyFlag(IRichEditOle *ole,int iFirst,int iLast)
|
|
|
{
|
|
|
ATLASSERT(m_pSmileyHost);
|
|
|
|
|
|
DWORD dwFlag =0;
|
|
|
for(int i=iFirst;i<=iLast;i++)
|
|
|
{
|
|
|
REOBJECT reobj={0};
|
|
|
reobj.cbStruct=sizeof(REOBJECT);
|
|
|
HRESULT hr=ole->GetObject(i,&reobj,REO_GETOBJ_NO_INTERFACES);
|
|
|
if(FAILED(hr)) break;
|
|
|
|
|
|
if (reobj.clsid==CLSID_SSmileyCtrl && reobj.dwUser==m_dwID)
|
|
|
{
|
|
|
//ѡ<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>Ʊ߿<EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ɫ
|
|
|
CHARRANGE chr={0};
|
|
|
m_pSmileyHost->SendMessage(EM_EXGETSEL, 0, (LPARAM)&chr,NULL);
|
|
|
|
|
|
if ( chr.cpMin!=chr.cpMax
|
|
|
&& (reobj.cp<chr.cpMax && reobj.cp>=chr.cpMin) )
|
|
|
{
|
|
|
if((chr.cpMax-chr.cpMin) > 1)
|
|
|
dwFlag=REO_INVERTEDSELECT;
|
|
|
else
|
|
|
dwFlag=REO_SELECTED;
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
return dwFlag;
|
|
|
}
|
|
|
|
|
|
void SSmileyCtrl::UpdateSmileyFlag()
|
|
|
{
|
|
|
if(!m_pSmileyHost) return ;
|
|
|
|
|
|
if(m_dwDrawFlag!=-1) return;
|
|
|
|
|
|
CComPtr<IRichEditOle> ole;
|
|
|
LRESULT lMsgRet = 0;
|
|
|
m_pSmileyHost->SendMessage(EM_GETOLEINTERFACE, 0, (LPARAM)&ole,&lMsgRet);
|
|
|
if (!lMsgRet) return;
|
|
|
|
|
|
//<EFBFBD><EFBFBD><EFBFBD>ÿɼ<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>Χ
|
|
|
m_pSmileyHost->SendMessage(EM_GETFIRSTVISIBLELINE,0,0,&lMsgRet);
|
|
|
|
|
|
int iFirstLine = (int)lMsgRet;
|
|
|
RECT rcView;
|
|
|
m_pSmileyHost->SendMessage(EM_GETRECT,0,(LPARAM)&rcView,&lMsgRet);
|
|
|
POINT pt={rcView.right+1,rcView.bottom-2};
|
|
|
|
|
|
m_pSmileyHost->SendMessage(EM_LINEINDEX,iFirstLine,0,&lMsgRet);
|
|
|
LONG cpFirst = (LONG)lMsgRet;
|
|
|
m_pSmileyHost->SendMessage(EM_CHARFROMPOS,0,(LPARAM)&pt,&lMsgRet);
|
|
|
LONG cpLast = (LONG)lMsgRet;
|
|
|
|
|
|
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڿɼ<EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD>е<EFBFBD>OLE<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
int nCount=ole->GetObjectCount();
|
|
|
|
|
|
int iFirstVisibleOle = FindFirstOleInrange(ole,0,nCount,cpFirst,cpLast);
|
|
|
if(iFirstVisibleOle==-1) return;
|
|
|
int iLastVisibleOle = FindLastOleInrange(ole,iFirstVisibleOle,nCount,cpFirst,cpLast);
|
|
|
|
|
|
m_dwDrawFlag = GetSmileyFlag(ole,iFirstVisibleOle,iLastVisibleOle);
|
|
|
}
|
|
|
|
|
|
STDMETHODIMP SSmileyCtrl::Clear()
|
|
|
{
|
|
|
memset(&m_rcPos,0,sizeof(RECT));
|
|
|
m_dwDrawFlag = -1;
|
|
|
return S_OK;
|
|
|
}
|
|
|
|
|
|
|
|
|
HRESULT CreateSmiley(REFIID riid,void ** ppUnk)
|
|
|
{
|
|
|
SSmileyCtrl * pRet = new SComObject<SSmileyCtrl>;
|
|
|
HRESULT hr = pRet->QueryInterface(riid,ppUnk);
|
|
|
if(hr != S_OK) delete pRet;
|
|
|
return hr;
|
|
|
}
|
|
|
|