Example #1
0
//需要用枚举的办法来获得指定OLE的显示位置,不知道有没有其它更好的办法。
BOOL CImageOle::GetOleRect( LPRECT lpRect )
{
	IRichEditOle *pRichEditOle=NULL;
	LRESULT lRes=m_pRichedit->DuiSendMessage(EM_GETOLEINTERFACE,0,(LPARAM)&pRichEditOle);
	if(!pRichEditOle) return FALSE;

	BOOL bRet=FALSE;

	int nObjCount = pRichEditOle->GetObjectCount();
	int i = 0;
	for (i = 0;i < nObjCount;i++)
	{	
		REOBJECT reo;
		ZeroMemory(&reo, sizeof(REOBJECT));
		reo.cbStruct = sizeof(REOBJECT);

		HRESULT hr = pRichEditOle->GetObject(i, &reo, REO_GETOBJ_POLEOBJ);
		if (hr != S_OK)
			continue;

		reo.poleobj->Release();

		if (reo.poleobj == (IOleObject *)this)
		{

			ITextDocument *pTextDocument = NULL;
			ITextRange *pTextRange = NULL;

			pRichEditOle->QueryInterface(IID_ITextDocument, (void **)&pTextDocument);
			if (!pTextDocument)
				break;

			long nLeft = 0;
			long nBottom = 0;
			pTextDocument->Range(reo.cp, reo.cp, &pTextRange);
			if (reo.dwFlags & REO_BELOWBASELINE)
				hr = pTextRange->GetPoint(TA_BOTTOM|TA_LEFT, &nLeft, &nBottom);
			else
				hr = pTextRange->GetPoint(TA_BASELINE|TA_LEFT, &nLeft, &nBottom);

			pTextDocument->Release();
			pTextRange->Release();

			CRect rcRichedit;
			GetWindowRect(m_pRichedit->GetContainer()->GetHostHwnd(),&rcRichedit);
			CSize szOle=m_pSkin->GetSkinSize();

			lpRect->left   = nLeft - rcRichedit.left;
			lpRect->bottom = nBottom - rcRichedit.top;
			lpRect->right  = lpRect->left + szOle.cx ;
			lpRect->top    = lpRect->bottom - szOle.cy;

			bRet=TRUE;
			break;
		}
	}

	pRichEditOle->Release();
	return bRet;
}
Example #2
0
BOOL RichEditPara::GetLineRect(int nLineNo, CRect& rcLine)
{
    rcLine.SetRectEmpty();

    int ncpStart;
    int nLength;
    m_pObjectHost->SendMessage(EM_LINEINDEX, nLineNo, 0, (LRESULT*)&ncpStart);
    m_pObjectHost->SendMessage(EM_LINELENGTH, ncpStart, 0, (LRESULT*)&nLength);

    SComPtr<ITextRange>  spRangeLine;
    ITextDocument * pdoc = m_pObjectHost->GetTextDoc();
    pdoc->Range(ncpStart, ncpStart + nLength, &spRangeLine);
    if (!spRangeLine)
    {
        return FALSE;
    }

    CHARRANGE chr = {ncpStart, ncpStart + nLength};
    // http://technet.microsoft.com/zh-cn/hh768766(v=vs.90) 新类型定义
#define _tomClientCoord     256  // 默认获取到的是屏幕坐标, Use client coordinates instead of screen coordinates.
#define _tomAllowOffClient  512  // Allow points outside of the client area.
    long lTypeTopLeft     = _tomAllowOffClient|_tomClientCoord|tomStart|TA_TOP|TA_LEFT;
    long lTypeRightBottom = _tomAllowOffClient|_tomClientCoord|tomEnd|TA_BOTTOM|TA_RIGHT;

    POINT   ptEnd, ptStart;
    spRangeLine->GetPoint(lTypeTopLeft,     &ptStart.x, &ptStart.y);
    spRangeLine->GetPoint(lTypeRightBottom, &ptEnd.x,   &ptEnd.y);

    rcLine.SetRect(ptStart, ptEnd);
    if (rcLine.Width() == 0) 
    {
        rcLine.right += 1;
    }

    return TRUE;
}
Example #3
0
static void SetPosition(HWND hwnd)
{
	IRichEditOle* RichEditOle;
	if (SendMessage(hwnd, EM_GETOLEINTERFACE, 0, (LPARAM)&RichEditOle) == 0)
		return;

	ITextDocument* TextDocument;
	if (RichEditOle->QueryInterface(IID_ITextDocument, (void**)&TextDocument) != S_OK) {
		RichEditOle->Release();
		return;
	}

	// retrieve text range
	ITextRange* TextRange;
	if (TextDocument->Range(0, 0, &TextRange) != S_OK) {
		TextDocument->Release();
		RichEditOle->Release();
		return;
	}
	TextDocument->Release();

	int objectCount = RichEditOle->GetObjectCount();
	for (int i = objectCount - 1; i >= 0; i--) {
		REOBJECT reObj = {0};
		reObj.cbStruct  = sizeof(REOBJECT);

		HRESULT hr = RichEditOle->GetObject(i, &reObj, REO_GETOBJ_POLEOBJ);
		if (FAILED(hr)) continue;

		ISmileyBase *igsc = NULL;
		if (reObj.clsid == CLSID_NULL) 
			reObj.poleobj->QueryInterface(IID_ISmileyAddSmiley, (void**) &igsc);

		reObj.poleobj->Release();
		if (igsc == NULL) continue;

		TextRange->SetRange(reObj.cp, reObj.cp);

		BOOL res;
		POINT pt;
		RECT rect;
		hr = TextRange->GetPoint(tomStart | TA_BOTTOM | TA_LEFT, &pt.x, &pt.y);
		if (hr == S_OK) {
			res = ScreenToClient(hwnd, &pt);
			rect.bottom = pt.y;
			rect.left = pt.x;
		}
		else rect.bottom = -1;

		hr = TextRange->GetPoint(tomStart | TA_TOP | TA_LEFT, &pt.x, &pt.y);
		if (hr == S_OK) {
			res = ScreenToClient(hwnd, &pt);
			rect.top = pt.y;
			rect.left = pt.x;
		}
		else rect.top = -1;

		igsc->SetPosition(hwnd, &rect);
		igsc->Release();
	}
	TextRange->Release();
	RichEditOle->Release();
}
Example #4
0
void RichEditPara::UpdatePosition()
{
    RichEditObj::UpdatePosition();

    if (m_bDisableLayout)
    {
        // 如果不需要布局,直接返回
        return;
    }

    CComPtr<ITextPara>   ppara;
    CComPtr<ITextRange>  prange;
    ITextDocument* pdoc = m_pObjectHost->GetTextDoc();

    CHARRANGE chr = m_chrContent;
    if (m_bBreakAtTheEnd)
    {
        chr.cpMax += 1;
    }

    pdoc->Range(chr.cpMin, chr.cpMax, &prange);
    prange->GetPara(&ppara);

    if (!m_bInited)
    {
        m_bInited = TRUE;
        ppara->SetSpaceBefore(px2pt(m_rcMargin.top));
        ppara->SetSpaceAfter(px2pt(m_rcMargin.bottom));
    }

    CRect rcAdjust    = m_pObjectHost->GetAdjustedRect();
    CRect rcClient    = m_pObjectHost->GetHostRect();
    int nLeftIndents    = m_alignType==ALIGN_RIGHT? m_rcMargin.right : m_rcMargin.left;
    int nRightIndents   = m_alignType==ALIGN_RIGHT? m_rcMargin.left: m_rcMargin.right;
    nRightIndents   += rcClient.Width() - rcAdjust.Width();// 计算真实的右边距

    // 尽量不要使用模拟计算,能提高速度
    if (!m_bSimulateAlign || m_alignType == ALIGN_LEFT)
    {
        m_bWrapped = IsWrapped();
        if (m_bNeedUpdateLayout)
        {
            int nAlign = tomAlignLeft;
            if (m_alignType == ALIGN_RIGHT)
                nAlign = tomAlignRight;
            else if (m_alignType == ALIGN_CENTER)
                nAlign = tomAlignCenter;

            ppara->SetAlignment(nAlign);
            ppara->SetIndents(0, px2pt(nLeftIndents), px2pt(nRightIndents));
            m_bNeedUpdateLayout = FALSE;
        }

        return;
    }

    /* 模拟计算右对齐
     * 注意:SetIndents和CalcParagraphRect很耗时,所以尽量不使用模拟计算靠右
     *
     * 1.先按最靠边的左右缩进设置
     * 2.按照cp计算段落的rect
     * 3.用richedit.width() - para.widht()计算左缩进,模拟右对齐
     * 4.根据计算出的左/缩进重新设置
    */ 

    // step 1
    ppara->SetIndents(0, px2pt(nLeftIndents), px2pt(nRightIndents));
    if ((m_bWrapped = IsWrapped()))
        return;

    // step 2
    CalcParagraphRect();

    // step 3
    if (m_alignType == ALIGN_RIGHT)
    {
        nLeftIndents = rcClient.Width() - m_rcObj.Width() - nRightIndents - 1; // 这里不减1,段落就换行了
    }
    else
    {
        int mid = (rcClient.Width() - m_rcObj.Width() - nRightIndents -nLeftIndents) / 2 - 1;
        nLeftIndents  = m_rcMargin.left + mid;
        nRightIndents = m_rcMargin.right + mid;
    }

    // step 4
    ppara->SetIndents(0, px2pt(nLeftIndents), px2pt(nRightIndents));
    m_bNeedUpdateLayout = FALSE;
    m_bDirty = TRUE;
}