第二章 第八小节Duilib中的CRichEditUI控件--富文本编辑框

  CRichEditUI控件是duilib中的富文本输入控件,以下则是常用参数设置。

<Font name="宋体" size="12" bold="false" italic="false" default="true" id="1"/>
<RichEdit name="广州知了软件有限公司" menu="true" font="1" bordersize="1" bordercolor="#FFDBDBDB" inset="2,2,2,2"/>

  上面的属性参数,属性列表中有解释,如下所示:

	<RichEdit parent="Container" notifies="setfocus killfocus timer menu return windowinit(root)">
		<Attribute name="name" default="" type="STRING" comment="控件名字,同一窗口内必须唯一,如(testbtn)"/>
		<Attribute name="pos" default="0,0,0,0" type="RECT" comment="位置,如果为float控件则指定位置和大小,否则只指定大小,如(0,0,100,100)"/>
		<Attribute name="padding" default="0,0,0,0" type="RECT" comment="外边距,如(2,2,2,2)"/>
		<Attribute name="bkcolor" default="0x00000000" type="DWORD" comment="背景颜色,如(0xFFFF0000)"/>
		<Attribute name="bkcolor2" default="0x00000000" type="DWORD" comment="背景渐变色2,和bkcolor配合使用,如(0xFFFFFF00)"/>
		<Attribute name="bkcolor3" default="0x00000000" type="DWORD" comment="背景渐变色3,和bkcolor、bkcolor2配合使用,如(0xFFFF00FF)"/>
		<Attribute name="bordercolor" default="0x00000000" type="DWORD" comment="边框颜色,如(0xFF000000)"/>
		<Attribute name="focusbordercolor" default="0x00000000" type="DWORD" comment="获得焦点时边框的颜色,如(0xFFFF0000)"/>
		<Attribute name="colorhsl" default="false" type="BOOL" comment="本控件的颜色是否随窗口的hsl变化而变化,如(false)"/>
		<Attribute name="bordersize" default="0" type="INT" comment="边框大小,如(1)"/>
		<Attribute name="borderround" default="0,0" type="SIZE" comment="边框圆角半径,如(2,2)"/>
		<Attribute name="bordervisible" default="false" type="BOOL" comment="是否显示边框"/>
		<Attribute name="bkimage" default="" type="STRING" comment="背景图片,如(bk.bmp或file='aaa.jpg' res='' restype='0' dest='0,0,0,0' source='0,0,0,0' corner='0,0,0,0' mask='#FF0000' fade='255' hole='false' xtiled='false' ytiled='false')"/>
		<Attribute name="width" default="0" type="INT" comment="控件预设的宽度,如(100)"/>
		<Attribute name="height" default="0" type="INT" comment="控件预设的高度,如(30)"/>
		<Attribute name="minwidth" default="0" type="INT" comment="控件的最小宽度,如(100)"/>
		<Attribute name="minheight" default="0" type="INT" comment="控件的最小高度,如(30)"/>
		<Attribute name="maxwidth" default="9999" type="INT" comment="控件的最大宽度,如(100)"/>
		<Attribute name="maxheight" default="9999" type="INT" comment="控件的最大高度,如(30)"/>
		<Attribute name="text" default="" type="STRING" comment="显示文本,如(测试文本)"/>
		<Attribute name="tooltip" default="" type="STRING" comment="鼠标悬浮提示,如(请在这里输入你的密码)"/>
		<Attribute name="userdata" default="" type="STRING" comment="自定义标识"/>
		<Attribute name="enabled" default="true" type="BOOL" comment="是否可以响应用户操作,如(true)"/>
		<Attribute name="mouse" default="true" type="BOOL" comment="本控件是否可以响应鼠标操作,如(true)"/>
		<Attribute name="mousechild" default="true" type="BOOL" comment="本控件的子控件是否可以响应用户操作,如(true)"/>
		<Attribute name="visible" default="true" type="BOOL" comment="是否可见,如(true)"/>
		<Attribute name="float" default="false" type="BOOL" comment="是否使用绝对定位,如(true)"/>
		<Attribute name="shortcut" default="" type="CHAR" comment="对应的快捷键,如(P)"/>
		<Attribute name="menu" default="false" type="BOOL" comment="是否需要右键菜单,如(true)"/>
		<Attribute name="inset" default="0,0,0,0" type="RECT" comment="容器的内边距,如(2,2,2,2)"/>
		<Attribute name="vscrollbar" default="false" type="BOOL" comment="是否使用竖向滚动条,如(true)"/>
		<Attribute name="autovscroll" default="false" type="BOOL" comment="是否随输入竖向滚动,如(true)"/>
		<Attribute name="hscrollbar" default="false" type="BOOL" comment="是否使用横向滚动条,如(true)"/>
		<Attribute name="autohscroll" default="false" type="BOOL" comment="是否随输入横向滚动,如(true)"/>
		<Attribute name="childpadding" default="0" type="INT" comment="子控件之间的额外距离,如(4)"/>
		<Attribute name="wanttab" default="true" type="BOOL" comment="是否接受tab按键消息,如(true)"/>
		<Attribute name="wantreturn" default="true" type="BOOL" comment="是否接受return按键消息,如(true)"/>
		<Attribute name="wantctrlreturn" default="true" type="BOOL" comment="是否接受ctrl+return按键消息,如(true)"/>
		<Attribute name="transparent" default="true" type="BOOL" comment="是否背景透明,如(true)"/>
		<Attribute name="rich" default="true" type="BOOL" comment="是否使用富格式,如(true)"/>
		<Attribute name="multiline" default="true" type="BOOL" comment="是否使用多行,如(true)"/>
		<Attribute name="readonly" default="false" type="BOOL" comment="是否只读,如(false)"/>
		<Attribute name="password" default="false" type="BOOL" comment="是否显示密码符,如(true)"/>
		<Attribute name="align" default="left" type="STRING" comment="文字对齐方式,取值left、right、cente,如(center)"/>
		<Attribute name="font" default="-1" type="INT" comment="字体id,如(0)"/>
		<Attribute name="textcolor" default="0xFF000000" type="DWORD" comment="字体颜色,如(0xFFFF0000)"/>
	</RichEdit>

  富文本编辑框是对win32 RichEdit的一种实现,源代码如下所示:

class CTxtWinHost;

    class UILIB_API CRichEditUI : public CContainerUI, public IMessageFilterUI
    {
        DECLARE_DUICONTROL(CRichEditUI)
    public:
        CRichEditUI();
        ~CRichEditUI();

        LPCTSTR GetClass() const;
        LPVOID GetInterface(LPCTSTR pstrName);
        UINT GetControlFlags() const;

        bool IsMultiLine();
        void SetMultiLine(bool bMultiLine);
        bool IsWantTab();
        void SetWantTab(bool bWantTab = true);
        bool IsWantReturn();
        void SetWantReturn(bool bWantReturn = true);
        bool IsWantCtrlReturn();
        void SetWantCtrlReturn(bool bWantCtrlReturn = true);
        bool IsTransparent();
        void SetTransparent(bool bTransparent = true);
        bool IsRich();
        void SetRich(bool bRich = true);
        bool IsReadOnly();
        void SetReadOnly(bool bReadOnly = true);
        bool IsWordWrap();
        void SetWordWrap(bool bWordWrap = true);
        int GetFont();
        void SetFont(int index);
        void SetFont(LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic);
        LONG GetWinStyle();
        void SetWinStyle(LONG lStyle);
        DWORD GetTextColor();
        void SetTextColor(DWORD dwTextColor);
        int GetLimitText();
        void SetLimitText(int iChars);
        long GetTextLength(DWORD dwFlags = GTL_DEFAULT) const;
        CDuiString GetText() const;
        void SetText(LPCTSTR pstrText);
        bool IsModify() const;
        void SetModify(bool bModified = true) const;
        void GetSel(CHARRANGE &cr) const;
        void GetSel(long& nStartChar, long& nEndChar) const;
        int SetSel(CHARRANGE &cr);
        int SetSel(long nStartChar, long nEndChar);
        void ReplaceSel(LPCTSTR lpszNewText, bool bCanUndo);
        void ReplaceSelW(LPCWSTR lpszNewText, bool bCanUndo = false);
        CDuiString GetSelText() const;
        int SetSelAll();
        int SetSelNone();
        WORD GetSelectionType() const;
        bool GetZoom(int& nNum, int& nDen) const;
        bool SetZoom(int nNum, int nDen);
        bool SetZoomOff();
        bool GetAutoURLDetect() const;
        bool SetAutoURLDetect(bool bAutoDetect = true);
        DWORD GetEventMask() const;
        DWORD SetEventMask(DWORD dwEventMask);
        CDuiString GetTextRange(long nStartChar, long nEndChar) const;
        void HideSelection(bool bHide = true, bool bChangeStyle = false);
        void ScrollCaret();
        int InsertText(long nInsertAfterChar, LPCTSTR lpstrText, bool bCanUndo = false);
        int AppendText(LPCTSTR lpstrText, bool bCanUndo = false);
        DWORD GetDefaultCharFormat(CHARFORMAT2 &cf) const;
        bool SetDefaultCharFormat(CHARFORMAT2 &cf);
        DWORD GetSelectionCharFormat(CHARFORMAT2 &cf) const;
        bool SetSelectionCharFormat(CHARFORMAT2 &cf);
        bool SetWordCharFormat(CHARFORMAT2 &cf);
        DWORD GetParaFormat(PARAFORMAT2 &pf) const;
        bool SetParaFormat(PARAFORMAT2 &pf);
        bool CanUndo();
        bool CanRedo();
        bool CanPaste();
        bool Redo();
        bool Undo();
        void Clear();
        void Copy();
        void Cut();
        void Paste();
        int GetLineCount() const;
        CDuiString GetLine(int nIndex, int nMaxLength) const;
        int LineIndex(int nLine = -1) const;
        int LineLength(int nLine = -1) const;
        bool LineScroll(int nLines, int nChars = 0);
        CDuiPoint GetCharPos(long lChar) const;
        long LineFromChar(long nIndex) const;
        CDuiPoint PosFromChar(UINT nChar) const;
        int CharFromPos(CDuiPoint pt) const;
        void EmptyUndoBuffer();
        UINT SetUndoLimit(UINT nLimit);
        long StreamIn(int nFormat, EDITSTREAM &es);
        long StreamOut(int nFormat, EDITSTREAM &es);
        void SetAccumulateDBCMode(bool bDBCMode);
        bool IsAccumulateDBCMode();

        RECT GetTextPadding() const;
        void SetTextPadding(RECT rc);
        LPCTSTR GetNormalImage();
        void SetNormalImage(LPCTSTR pStrImage);
        LPCTSTR GetHotImage();
        void SetHotImage(LPCTSTR pStrImage);
        LPCTSTR GetFocusedImage();
        void SetFocusedImage(LPCTSTR pStrImage);
        LPCTSTR GetDisabledImage();
        void SetDisabledImage(LPCTSTR pStrImage);
        void PaintStatusImage(HDC hDC);

        void SetTipValue(LPCTSTR pStrTipValue);
        LPCTSTR GetTipValue();
        void SetTipValueColor(LPCTSTR pStrColor);
        DWORD GetTipValueColor();
        void SetTipValueAlign(UINT uAlign);
        UINT GetTipValueAlign();

        void DoInit();
        bool SetDropAcceptFile(bool bAccept);
        // 注意:TxSendMessage和SendMessage是有区别的,TxSendMessage没有multibyte和unicode自动转换的功能,
        // 而richedit2.0内部是以unicode实现的,在multibyte程序中,必须自己处理unicode到multibyte的转换
        virtual HRESULT TxSendMessage(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT *plresult) const; 
        IDropTarget* GetTxDropTarget();
        virtual bool OnTxViewChanged();
        virtual void OnTxNotify(DWORD iNotify, void *pv);

        void SetScrollPos(SIZE szPos, bool bMsg = true);
        void LineUp();
        void LineDown();
        void PageUp();
        void PageDown();
        void HomeUp();
        void EndDown();
        void LineLeft();
        void LineRight();
        void PageLeft();
        void PageRight();
        void HomeLeft();
        void EndRight();

        SIZE EstimateSize(SIZE szAvailable);
        void SetPos(RECT rc, bool bNeedInvalidate = true);
        void Move(SIZE szOffset, bool bNeedInvalidate = true);
        void DoEvent(TEventUI& event);
        bool DoPaint(HDC hDC, const RECT& rcPaint, CControlUI* pStopControl);

        void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);

        LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled);

    protected:
        enum { 
            DEFAULT_TIMERID = 20,
        };

        CTxtWinHost* m_pTwh;
        bool m_bVScrollBarFixing;
        bool m_bWantTab;
        bool m_bWantReturn;
        bool m_bWantCtrlReturn;
        bool m_bTransparent;
        bool m_bRich;
        bool m_bReadOnly;
        bool m_bWordWrap;
        DWORD m_dwTextColor;
        int m_iFont;
        int m_iLimitText;
        LONG m_lTwhStyle;
        bool m_bDrawCaret;
        bool m_bInited;

        bool  m_fAccumulateDBC ; // TRUE - need to cumulate ytes from 2 WM_CHAR msgs
        // we are in this mode when we receive VK_PROCESSKEY
        UINT m_chLeadByte; // use when we are in _fAccumulateDBC mode

        RECT m_rcTextPadding;
        UINT m_uButtonState;
        CDuiString m_sNormalImage;
        CDuiString m_sHotImage;
        CDuiString m_sFocusedImage;
        CDuiString m_sDisabledImage;
        CDuiString m_sTipValue;
        DWORD m_dwTipValueColor;
        UINT m_uTipValueAlign;
    };

  除此之外,查看下两个关键函数的实现,DoEvent函数和DoPaint函数,这个实现与CEditUI对象不同,它把所有的消息转发给富文本控件。

void CRichEditUI::DoEvent(TEventUI& event)
    {
        if( !IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND ) {
            if( m_pParent != NULL ) m_pParent->DoEvent(event);
            else CControlUI::DoEvent(event);
            return;
        }

        if( event.Type == UIEVENT_SETCURSOR && IsEnabled() )
        {
            if( m_pTwh && m_pTwh->DoSetCursor(NULL, &event.ptMouse) ) {
                return;
            }
        }
        else if( event.Type == UIEVENT_WINDOWSIZE ) {
            if( m_pTwh ) m_pTwh->NeedFreshCaret();
        }
        else if( event.Type == UIEVENT_SETFOCUS ) {
            if( m_pTwh ) {
                m_pTwh->OnTxInPlaceActivate(NULL);
                m_pTwh->GetTextServices()->TxSendMessage(WM_SETFOCUS, 0, 0, 0);
            }
            m_bFocused = true;
            Invalidate();
            return;
        }
        if( event.Type == UIEVENT_KILLFOCUS )  {
            if( m_pTwh ) {
                m_pTwh->OnTxInPlaceActivate(NULL);
                m_pTwh->GetTextServices()->TxSendMessage(WM_KILLFOCUS, 0, 0, 0);
            }
            m_bFocused = false;
            Invalidate();
            return;
        }
        else if( event.Type == UIEVENT_TIMER ) {
            if( event.wParam == DEFAULT_TIMERID ) {
                if( m_pTwh && m_pManager->IsLayered() && IsFocused() ) {
                    if (::GetFocus() != m_pManager->GetPaintWindow()) return;
                    m_bDrawCaret = !m_bDrawCaret;
                    POINT ptCaret;
                    ::GetCaretPos(&ptCaret);
                    RECT rcCaret = { ptCaret.x, ptCaret.y, ptCaret.x + m_pTwh->GetCaretWidth(), 
                        ptCaret.y + m_pTwh->GetCaretHeight() };
                    RECT rcTemp = rcCaret;
                    if( !::IntersectRect(&rcCaret, &rcTemp, &m_rcItem) ) return;
                    CControlUI* pParent = this;
                    RECT rcParent;
                    while( pParent = pParent->GetParent() ) {
                        rcTemp = rcCaret;
                        rcParent = pParent->GetPos();
                        if( !::IntersectRect(&rcCaret, &rcTemp, &rcParent) ) {
                            return;
                        }
                    }                    
                    m_pManager->Invalidate(rcCaret);
                }
                return;
            }
            if( m_pTwh ) {
                m_pTwh->GetTextServices()->TxSendMessage(WM_TIMER, event.wParam, event.lParam, 0);
            } 
            return;
        }
        if( event.Type == UIEVENT_SCROLLWHEEL ) {
            if( (event.wKeyState & MK_CONTROL) != 0  ) {
                return;
            }
        }
        if( event.Type == UIEVENT_BUTTONDOWN || event.Type == UIEVENT_DBLCLICK ) 
        {
            return;
        }
        if( event.Type == UIEVENT_MOUSEMOVE ) 
        {
            return;
        }
        if( event.Type == UIEVENT_BUTTONUP ) 
        {
            return;
        }
        if( event.Type > UIEVENT__KEYBEGIN && event.Type < UIEVENT__KEYEND )
        {
            return;
        }
        CContainerUI::DoEvent(event);
    }

  另外一个函数是DoPaint函数,代码如下:

 bool CRichEditUI::DoPaint(HDC hDC, const RECT& rcPaint, CControlUI* pStopControl)
    {
        RECT rcTemp = { 0 };
        if( !::IntersectRect(&rcTemp, &rcPaint, &m_rcItem) ) return true;

        CRenderClip clip;
        CRenderClip::GenerateClip(hDC, rcTemp, clip);
        CControlUI::DoPaint(hDC, rcPaint, pStopControl);//父控件绘制

        if( m_pTwh ) {//富文本框绘制
            RECT rc;
            m_pTwh->GetControlRect(&rc);
            // Remember wparam is actually the hdc and lparam is the update
            // rect because this message has been preprocessed by the window.
            m_pTwh->GetTextServices()->TxDraw(
                DVASPECT_CONTENT,          // Draw Aspect
                /*-1*/0,                // Lindex
                NULL,                    // Info for drawing optimazation
                NULL,                    // target device information
                hDC,                    // Draw device HDC
                NULL,                        // Target device HDC
                (RECTL*)&rc,            // Bounding client rectangle
                NULL,                     // Clipping rectangle for metafiles
                (RECT*)&rcPaint,        // Update rectangle
                NULL,                        // Call back function
                NULL,                    // Call back parameter
                0);                        // What view of the object
            if( m_bVScrollBarFixing ) {
                LONG lWidth = rc.right - rc.left + m_pVerticalScrollBar->GetFixedWidth();
                LONG lHeight = 0;
                SIZEL szExtent = { -1, -1 };
                m_pTwh->GetTextServices()->TxGetNaturalSize(
                    DVASPECT_CONTENT, 
                    GetManager()->GetPaintDC(), 
                    NULL,
                    NULL,
                    TXTNS_FITTOCONTENT,
                    &szExtent,
                    &lWidth,
                    &lHeight);
                if( lHeight <= rc.bottom - rc.top ) {
                    NeedUpdate();
                }
            }
        }
		//其它子控件绘制
        if( m_items.GetSize() > 0 ) {
            RECT rc = m_rcItem;
            rc.left += m_rcInset.left;
            rc.top += m_rcInset.top;
            rc.right -= m_rcInset.right;
            rc.bottom -= m_rcInset.bottom;
            if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible() ) rc.right -= m_pVerticalScrollBar->GetFixedWidth();
            if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() ) rc.bottom -= m_pHorizontalScrollBar->GetFixedHeight();

            if( !::IntersectRect(&rcTemp, &rcPaint, &rc) ) {
                for( int it = 0; it < m_items.GetSize(); it++ ) {
                    CControlUI* pControl = static_cast<CControlUI*>(m_items[it]);
                    if( pControl == pStopControl ) return false;
                    if( !pControl->IsVisible() ) continue;
                    if( !::IntersectRect(&rcTemp, &rcPaint, &pControl->GetPos()) ) continue;
                    if( pControl->IsFloat() ) {
                        if( !::IntersectRect(&rcTemp, &m_rcItem, &pControl->GetPos()) ) continue;
                        if( !pControl->Paint(hDC, rcPaint, pStopControl) ) return false;
                    }
                }
            }
            else {
                CRenderClip childClip;
                CRenderClip::GenerateClip(hDC, rcTemp, childClip);
                for( int it = 0; it < m_items.GetSize(); it++ ) {
                    CControlUI* pControl = static_cast<CControlUI*>(m_items[it]);
                    if( pControl == pStopControl ) return false;
                    if( !pControl->IsVisible() ) continue;
                    if( !::IntersectRect(&rcTemp, &rcPaint, &pControl->GetPos()) ) continue;
                    if( pControl->IsFloat() ) {
                        if( !::IntersectRect(&rcTemp, &m_rcItem, &pControl->GetPos()) ) continue;
                        CRenderClip::UseOldClipBegin(hDC, childClip);
                        if( !pControl->Paint(hDC, rcPaint, pStopControl) ) return false;
                        CRenderClip::UseOldClipEnd(hDC, childClip);
                    }
                    else {
                        if( !::IntersectRect(&rcTemp, &rc, &pControl->GetPos()) ) continue;
                        if( !pControl->Paint(hDC, rcPaint, pStopControl) ) return false;
                    }
                }
            }
        }

  CRichEditUI控件是富文本编辑框控件,同时它也是一个容器控件,可以非常方便的加入子控件。同时通过查找控件函数,找到子控件。


  欢迎光临知了软件开发网络平台,本公司定制开发各类软件,主要方向为桌面专业软件开发和插件定制开发,桌面软件主要包括文字图形识别类软件,信息管理类软件,3D打印类软件,视频类软件以及其它涉及专业的各类图形图像处理软件。插件包含AE插件,AI插件,PS插件,PDF插件,3DMAX插件以及Word,Excel等Office插件开发。详情请咨询,微信QQ:312117271,手机:18928899728,邮箱: anjingzhi_sea@163.com.
公司网址:http://www.zhiliaos.com

相关推荐
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页