netease-im / NIM_Duilib_Framework

网易云信Windows应用开发框架。
MIT License
2.09k stars 834 forks source link

控件不响应接收不到 #463

Open alancaven opened 2 years ago

alancaven commented 2 years ago

移植原版DUILIB的EDIT控件时,发现EDIT的窗口无法接收到OCM_COMMAND消息,请问需要怎样解决

nmgwddj commented 1 year ago

请将您移植的代码示例通过示例代码的方式或者仓库的方式提供,我们一起来看一下。

alancaven commented 1 year ago

`#ifndef __UIEDIT_H__

define __UIEDIT_H__

pragma once

namespace ui { class EditWnd;

class UILIB_API EditUI : public Control
{
    friend class EditWnd;
public:
    EditUI();
    /// 重写父类方法,提供个性化功能,请参考父类声明
    virtual std::wstring GetType() const override;
    virtual void DoInit() override;
    virtual UINT GetControlFlags() const override;
    virtual void HandleMessage(EventArgs& msg) override;
    virtual void SetAttribute(const std::wstring& strName, const std::wstring& strValue) override;
    /// 渲染部分
    virtual void PaintText(IRenderContext* pRender) override;
    virtual void PaintChild(IRenderContext* pRender, const UiRect& rcPaint) override;
    virtual void PaintStatusImage(IRenderContext* pRender) override;

    void SetEnabled(bool bEnable = true);
    void SetMaxChar(UINT uMax);
    UINT GetMaxChar();
    void SetReadOnly(bool bReadOnly);
    bool IsReadOnly() const;
    void SetPasswordMode(bool bPasswordMode);
    bool IsPasswordMode() const;
    void SetPasswordChar(TCHAR cPasswordChar);
    TCHAR GetPasswordChar() const;
    void SetNumberOnly(bool bNumberOnly);
    bool IsNumberOnly() const;
    void SetLowerCase(bool bLowerCase);
    bool IsLowerCase() const;
    void SetUpperCase(bool bUpperCase);
    bool IsUpperCase() const;
    int GetWindowStyls() const;

    void SetNativeEditBkColor(DWORD dwBkColor);
    DWORD GetNativeEditBkColor() const;
    void SetNativeEditTextColor( LPCTSTR pStrColor );
    DWORD GetNativeEditTextColor() const;

    void SetPos(RECT rc, bool bNeedInvalidate = true);
    void SetVisible(bool bVisible = true);
    void SetInternVisible(bool bVisible = true);

    virtual std::wstring GetText() const;
    virtual void SetText(const std::wstring& strText);
    /**
     * @brief 设置文本样式
     * @param[in] uStyle 要设置的样式
     * @return 无
     */
    void SetTextStyle(UINT uStyle);

    /**
     * @brief 获取文本样式
     * @return 返回文本样式
     */
    UINT GetTextStyle() const;
    /**
     * @brief 获取文字边距
     * @return 返回文字的边距信息
     */
    UiRect GetTextPadding() const;

    /**
     * @brief 设置文字边距信息
     * @param[in] rc 边距信息
     * @return 无
     */
    void SetTextPadding(UiRect rc);

    /**
     * @brief 获取当前字体编号
     * @return 返回字体编号,该编号在 global.xml 中标识
     */
    std::wstring GetFont() const;

    /**
     * @brief 设置当前字体
     * @param[in] index 要设置的字体编号,该编号必须在 global.xml 中存在
     * @return 无
     */
    void SetFont(const std::wstring& strFontId);
    /**
     * @brief 设置是否显示提示文字
     * @param[in] bPrompt 设置为 true 为显示,false 为不显示
     * @return 无
     */
    void SetPromptMode(bool bPrompt);

    /**
     * @brief 获取提示文字
     * @return 返回提示文字内容
     */
    std::wstring GetPromptText() const;
    /**
     * @brief 设置提示文字
     * @param[in] strText 要设置的提示文字
     * @return 无
     */
    void SetPromptText(const std::wstring& strText);
    /**
     * @brief 绘制提示文字
     * @param[in] pRender 绘制引擎
     * @return 无
     */
    void PaintPromptText(IRenderContext* pRender);
    /**
     * @brief 创建光标
     * @param[in] xWidth 光标宽度
     * @param[in] yHeight 光标高度
     * @return 成功返回 true,失败返回 false
     */
    BOOL CreateCaret(INT xWidth, INT yHeight);

    /**
     * @brief 设置是否显示光标
     * @param[in] fShow 设置 true 为显示,false 为不显示
     * @return 成功返回 true,失败返回 false
     */
    BOOL ShowCaret(BOOL fShow);

    /**
     * @brief 设置光标颜色
     * @param[in] dwColor 要设置的颜色值,该值必须在 global.xml 中存在
     * @return 无
     */
    void SetCaretColor(const std::wstring& dwColor);

    /**
     * @brief 获取光标颜色
     * @return 返回光标颜色
     */
    std::wstring GetCaretColor();

    /**
     * @brief 获取光标矩形位置
     * @return 返回光标矩形位置
     */
    RECT GetCaretRect();

    /**
     * @brief 设置光标位置
     * @param[in] x X 轴坐标
     * @param[in] y Y 轴坐标
     * @return 成功返回 true,失败返回 false
     */
    BOOL SetCaretPos(INT x, INT y);

    /**
     * @brief 切换光标是否显示
     * @return 无
     */
    void ChangeCaretVisiable();

    /**
     * @brief 切换光标是否显示
     * @return 无
     */
    bool IsCaretVisiable() { return m_bIsCaretVisiable; }

    /**
     * @brief 绘制光标
     * @param[in] pRender 绘制引擎
     * @param[in] rcPaint 绘制位置
     * @return 无
     */
    void PaintCaret(IRenderContext* pRender, const UiRect& rcPaint);

    /**
     * @brief 设置只读模式不显示光标
     * @return 无
     */
    void SetNoCaretReadonly();

protected:
    bool    m_bInited;
    EditWnd* m_pWindow;

    UINT m_uMaxChar;
    bool m_bReadOnly;
    bool m_bPasswordMode;
    TCHAR m_cPasswordChar;
    UINT m_uButtonState;
    DWORD m_dwEditbkColor;
    DWORD m_dwEditTextColor;
    int m_iWindowStyls;
    //
    std::wstring    m_sText;
    std::wstring m_sFontId;
    UiRect  m_rcTextPadding;
    UINT    m_uTextStyle;
    //编辑框提示信息
    bool m_bAllowPrompt;
    std::wstring m_sPromptColor;
    std::wstring m_sPromptText;
    //光标相关
    bool m_bNoCaretReadonly;
    bool m_bIsCaretVisiable;
    int  m_iCaretPosX;
    int  m_iCaretPosY;
    int  m_iCaretWidth;
    int  m_iCaretHeight;
    std::wstring m_sCaretColor;
    nbase::WeakCallbackFlag m_drawCaretFlag;
};

}

endif // __UIEDIT_H__

include "StdAfx.h"

include "Edit.h"

include

namespace ui { class EditWnd : public Window {

public:
    EditWnd();

    void Init(EditUI* pOwner);
    RECT CalPos();

    virtual std::wstring GetWindowClassName() const override;
    virtual std::wstring GetSuperClassName() const override;
    virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override;
    LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    LRESULT OnEditChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

protected:
    virtual void OnFinalMessage(HWND hWnd) override;

protected:
    EditUI* m_pOwner;
    HBRUSH m_hBkBrush;
    bool m_bInit;
};

EditWnd::EditWnd() : 
    m_pOwner(nullptr),
    m_hBkBrush(NULL),
    m_bInit(false)
{
}

void EditWnd::Init(EditUI* pOwner)
{
    m_pOwner = pOwner;
    ui::UiRect rcPos = CalPos();
    UINT uStyle = 0;
    if(m_pOwner->GetWindow()->IsLayeredWindow()) 
    {
        uStyle = WS_POPUP | ES_AUTOHSCROLL | WS_VISIBLE;
        RECT rcWnd = { 0 };
        ::GetWindowRect(m_pOwner->GetWindow()->GetHWND(), &rcWnd);
        rcPos.left += rcWnd.left;
        rcPos.right += rcWnd.left;
        rcPos.top += rcWnd.top - 1;
        rcPos.bottom += rcWnd.top - 1;
    }
    else 
    {
        uStyle = WS_CHILD | ES_AUTOHSCROLL;
    }
    UINT uTextStyle = m_pOwner->GetTextStyle();
    if(uTextStyle & DT_LEFT) uStyle |= ES_LEFT;
    else if(uTextStyle & DT_CENTER) uStyle |= ES_CENTER;
    else if(uTextStyle & DT_RIGHT) uStyle |= ES_RIGHT;
    if( m_pOwner->IsPasswordMode() ) uStyle |= ES_PASSWORD;
    Create(m_pOwner->m_pWindow->GetHWND(), NULL, uStyle, 0, m_pOwner->GetWindow()->IsLayeredWindow(), rcPos);

    HFONT hFont = GlobalManager::GetFont(m_pOwner->GetFont());
    SetWindowFont(m_hWnd, hFont, TRUE);

    Edit_LimitText(m_hWnd, m_pOwner->GetMaxChar());
    if( m_pOwner->IsPasswordMode() ) Edit_SetPasswordChar(m_hWnd, m_pOwner->GetPasswordChar());

    Edit_SetText(m_hWnd, m_pOwner->GetText().c_str());
    Edit_SetModify(m_hWnd, FALSE);
    SendMessage(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELPARAM(0, 0));
    Edit_Enable(m_hWnd, m_pOwner->IsEnabled() == true);
    Edit_SetReadOnly(m_hWnd, m_pOwner->IsReadOnly() == true);

    //Styls
    LONG styleValue = ::GetWindowLong(m_hWnd, GWL_STYLE);
    styleValue |= pOwner->GetWindowStyls();
    ::SetWindowLong(GetHWND(), GWL_STYLE, styleValue);
    ::ShowWindow(m_hWnd, SW_SHOWNOACTIVATE);
    ::SetFocus(m_hWnd);
    m_bInit = true;
}

RECT EditWnd::CalPos()
{
    UiRect rcPos = m_pOwner->GetPos();
    RECT rcInset = m_pOwner->GetTextPadding();
    rcPos.left += rcInset.left;
    rcPos.top += rcInset.top;
    rcPos.right -= rcInset.right;
    rcPos.bottom -= rcInset.bottom;
    LONG lEditHeight = GlobalManager::GetTFontInfo(m_pOwner->GetFont())->tm.tmHeight;
    if (lEditHeight < rcPos.GetHeight()) {
        rcPos.top += (rcPos.GetHeight() - lEditHeight) / 2;
        rcPos.bottom = rcPos.top + lEditHeight;
    }
    return rcPos;
}

std::wstring EditWnd::GetWindowClassName() const
{
    return _T("EditWnd");
}

std::wstring EditWnd::GetSuperClassName() const
{
    return WC_EDIT;
}

void EditWnd::OnFinalMessage(HWND hWnd)
{
    m_pOwner->Invalidate();
    // Clear reference and die
    if (m_hBkBrush != NULL) ::DeleteObject(m_hBkBrush);
    m_pOwner->m_pWindow = NULL;
    delete this;
}

LRESULT EditWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    //char szDebug[32];
    //sprintf(szDebug, "uMsg:%d", uMsg);
    //OutputDebugStringA(szDebug);

    LRESULT lRes = 0;
    BOOL bHandled = TRUE;
    if (uMsg == WM_KILLFOCUS) lRes = OnKillFocus(uMsg, wParam, lParam, bHandled);
    else if( uMsg == OCM_COMMAND ) 
    {
        OutputDebugStringA("OCM_COMMAND");
        if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE)
        {
            OutputDebugStringA("EN_CHANGE");
            lRes = OnEditChanged(uMsg, wParam, lParam, bHandled);
        }
        else if( GET_WM_COMMAND_CMD(wParam, lParam) == EN_UPDATE ) {
            OutputDebugStringA("EN_UPDATE");
            RECT rcClient;
            ::GetClientRect(m_hWnd, &rcClient);
            ::InvalidateRect(m_hWnd, &rcClient, FALSE);
        }
    }
    else if (uMsg == WM_NOTIFY)
    {
        OutputDebugStringA("WM_NOTIFY");
    }
    else if( uMsg == WM_KEYDOWN && TCHAR(wParam) == VK_RETURN ){
        m_pOwner->GetWindow()->SendNotify(m_pOwner, kEventReturn);
    }
    else if( uMsg == WM_KEYDOWN && TCHAR(wParam) == VK_TAB ){
        if (m_pOwner->GetWindow()->IsLayeredWindow()) 
        {
            m_pOwner->GetWindow()->SetNextTabControl();
        }
    }
    else if( uMsg == OCM__BASE + WM_CTLCOLOREDIT  || uMsg == OCM__BASE + WM_CTLCOLORSTATIC ) {
        if (m_pOwner->GetNativeEditBkColor() == 0xFFFFFFFF) return NULL;
        ::SetBkMode((HDC)wParam, TRANSPARENT);

        DWORD dwTextColor;
        if (m_pOwner->GetNativeEditTextColor() != 0x000000)
            dwTextColor = m_pOwner->GetNativeEditTextColor();
        else
            dwTextColor = 0xFFFFFFFF;// m_pOwner->GetTextColor();

        ::SetTextColor((HDC)wParam, RGB(GetBValue(dwTextColor), GetGValue(dwTextColor), GetRValue(dwTextColor)));
        if (m_hBkBrush == NULL) {
            DWORD clrColor = m_pOwner->GetNativeEditBkColor();
            m_hBkBrush = ::CreateSolidBrush(RGB(GetBValue(clrColor), GetGValue(clrColor), GetRValue(clrColor)));
        }
        return (LRESULT)m_hBkBrush;
    }
    else bHandled = FALSE;

    if (!bHandled) return Window::HandleMessage(uMsg, wParam, lParam);
    return lRes;
}

LRESULT EditWnd::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    LRESULT lRes = ::DefWindowProc(m_hWnd, uMsg, wParam, lParam);
    PostMessage(WM_CLOSE);
    return lRes;
}

LRESULT EditWnd::OnEditChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
    if (!m_bInit) return 0;
    if (m_pOwner == NULL) return 0;
    // Copy text back
    int cchLen = ::GetWindowTextLength(m_hWnd) + 1;
    LPTSTR pstr = static_cast<LPTSTR>(_alloca(cchLen * sizeof(TCHAR)));
    ASSERT(pstr);
    if( pstr == NULL ) return 0;
    ::GetWindowText(m_hWnd, pstr, cchLen);
    OutputDebugString(pstr);

    m_pOwner->m_sText = pstr;
    m_pOwner->GetWindow()->SendNotify(m_pOwner, kEventTextChange);
    return 0;
}

/////////////////////////////////////////////////////////////////////////////////////
//
//
EditUI::EditUI() : 
    m_bInited(false),
    m_pWindow(NULL), 
    m_uMaxChar(255), 
    m_bReadOnly(false),
    m_bPasswordMode(false), 
    m_cPasswordChar(_T('*')), 
    m_uButtonState(0), 
    m_dwEditbkColor(0xFFFFFFFF), 
    m_dwEditTextColor(0x00000000), 
    m_iWindowStyls(0),
    m_bNoCaretReadonly(false),
    m_bIsCaretVisiable(false),
    m_iCaretPosX(0),
    m_iCaretPosY(0),
    m_iCaretWidth(0),
    m_iCaretHeight(0),
    m_drawCaretFlag(),
    m_sFontId(),
    m_sText(),
    m_uTextStyle(DT_LEFT | DT_TOP | DT_END_ELLIPSIS | DT_NOCLIP | DT_SINGLELINE),
    m_rcTextPadding(),
    m_bAllowPrompt(false),
    m_sPromptText(),
    m_sPromptColor()
{
    SetTextPadding(ui::UiRect(4, 3, 4, 3));
    SetBkColor(L"white");
}

std::wstring EditUI::GetType() const
{
    return DUI_CTR_EDIT;
}

void EditUI::DoInit()
{
    if (m_bInited)
        return;
    //创建光标
    CreateCaret(1, (INT)(GlobalManager::GetTFontInfo(GetFont())->tm.tmHeight));

    m_bInited = true;

}
UINT EditUI::GetControlFlags() const
{
    return IsEnabled() && IsAllowTabStop() ? UIFLAG_TABSTOP : UIFLAG_DEFAULT;
}

void EditUI::HandleMessage(EventArgs& event)
{
    if( !IsMouseEnabled() && event.Type > kEventMouseBegin && event.Type < kEventMouseEnd ) {
        if (m_pParent != NULL) m_pParent->HandleMessageTemplate(event);
        else __super::HandleMessage(event);
        return;
    }

    if( event.Type == kEventSetCursor && IsEnabled() )
    {
        ::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_IBEAM)));
        return;
    }
    if( event.Type == kEventWindowSize )
    {
        if (m_pWindow != NULL)
        {
            m_pWindow->SetFocusNeeded(this);
        }
    }
    if( event.Type == kEventMouseScrollWheel )
    {
        if( m_pWindow != NULL ) return;
    }
    if( event.Type == kEventSetFocus && IsEnabled() ) 
    {
        ShowCaret(true);

        if(m_pWindow) return;
        m_pWindow = new EditWnd();
        ASSERT(m_pWindow);
        m_pWindow->Init(this);
        OutputDebugStringA("kEventSetFocus");

        Invalidate();
    }
    if( event.Type == kEventKillFocus && IsEnabled() ) 
    {
        ShowCaret(false);
        OutputDebugStringA("kEventKillFocus");
        Invalidate();
    }
    if( event.Type == kEventMouseButtonDown || event.Type == kEventMouseDoubleClick || event.Type == kEventMouseRightButtonDown) 
    {
        if( IsEnabled() ) {
            GetWindow()->ReleaseCapture();
            if( IsFocused() && m_pWindow == NULL )
            {
                m_pWindow = new EditWnd();
                ASSERT(m_pWindow);
                m_pWindow->Init(this);

                if( PtInRect(&m_rcItem, event.ptMouse) )
                {
                    int nSize = GetWindowTextLength(m_pWindow->GetHWND());
                    if( nSize == 0 ) nSize = 1;
                    Edit_SetSel(m_pWindow->GetHWND(), 0, nSize);
                }
                else if (m_pWindow != NULL)
                {

if 1

                    int nSize = GetWindowTextLength(m_pWindow->GetHWND());
                    if (nSize == 0)
                        nSize = 1;

                    Edit_SetSel(m_pWindow->GetHWND(), 0, nSize);

else

                    POINT pt = event.ptMouse;
                    pt.x -= m_rcItem.left + m_rcTextPadding.left;
                    pt.y -= m_rcItem.top + m_rcTextPadding.top;
                    ::SendMessage(*m_pWindow, WM_LBUTTONDOWN, event.wParam, MAKELPARAM(pt.x, pt.y));

endif

                }
            }
        }
        return;
    }
    if (event.Type == kEventMouseMove)
    {
        return;
    }
    if (event.Type == kEventMouseButtonUp)
    {
        return;
    }
    if (event.Type == kEventMouseMenu)
    {
        return;
    }
    __super::HandleMessage(event);
}

std::wstring EditUI::GetText() const
{
    return m_sText;
}

void EditUI::SetText(const std::wstring& strText)
{
    m_sText = strText;
    if (m_pWindow != NULL) Edit_SetText(m_pWindow->GetHWND(), m_sText.c_str());
    Invalidate();
}

std::wstring EditUI::GetFont() const
{
    return m_sFontId;
}

void EditUI::SetFont(const std::wstring& strFontId)
{
    m_sFontId = strFontId;
    this->Invalidate();
}
void EditUI::SetEnabled(bool bEnable)
{
    __super::SetEnabled(bEnable);
    if( !IsEnabled() ) {
        m_uButtonState = 0;
    }
}

UiRect EditUI::GetTextPadding() const
{
    return m_rcTextPadding;
}

void EditUI::SetTextPadding(UiRect rc)
{
    DpiManager::GetInstance()->ScaleRect(rc);
    m_rcTextPadding = rc;
    if (this->GetFixedWidth() == DUI_LENGTH_AUTO || this->GetFixedHeight() == DUI_LENGTH_AUTO) {
        this->ArrangeAncestor();
    }
    else {
        this->Invalidate();
    }
}

void EditUI::SetMaxChar(UINT uMax)
{
    m_uMaxChar = uMax;
    if( m_pWindow != NULL ) Edit_LimitText(m_pWindow->GetHWND(), m_uMaxChar);
}

UINT EditUI::GetMaxChar()
{
    return m_uMaxChar;
}

void EditUI::SetReadOnly(bool bReadOnly)
{
    if( m_bReadOnly == bReadOnly ) return;

    m_bReadOnly = bReadOnly;
    if( m_pWindow != NULL ) Edit_SetReadOnly(m_pWindow->GetHWND(), m_bReadOnly);
    Invalidate();
}

bool EditUI::IsReadOnly() const
{
    return m_bReadOnly;
}

void EditUI::SetNumberOnly(bool bNumberOnly)
{
    if( bNumberOnly )
    {
        m_iWindowStyls |= ES_NUMBER;
    }
    else
    {
        m_iWindowStyls &= ~ES_NUMBER;
    }
}

bool EditUI::IsNumberOnly() const
{
    return (m_iWindowStyls & ES_NUMBER) ? true:false;
}

void EditUI::SetLowerCase(bool bLowerCase)
{
    if( bLowerCase )
    {
        m_iWindowStyls |= ES_LOWERCASE;
    }
    else
    {
        m_iWindowStyls &= ~ES_LOWERCASE;
    }
}
bool EditUI::IsLowerCase() const { return (m_iWindowStyls & ES_LOWERCASE) ? true:false; }

void EditUI::SetUpperCase(bool bUpperCase)
{
    if( bUpperCase )
    {
        m_iWindowStyls |= ES_UPPERCASE;
    }
    else
    {
        m_iWindowStyls &= ~ES_UPPERCASE;
    }
}
bool EditUI::IsUpperCase() const { return (m_iWindowStyls & ES_UPPERCASE) ? true:false; }

int EditUI::GetWindowStyls() const 
{
    return m_iWindowStyls;
}

void EditUI::SetPasswordMode(bool bPasswordMode)
{
    if( m_bPasswordMode == bPasswordMode ) return;
    m_bPasswordMode = bPasswordMode;
    Invalidate();
    if( m_pWindow != NULL ) {
        LONG styleValue = ::GetWindowLong(m_pWindow->GetHWND(), GWL_STYLE);
        bPasswordMode ? styleValue |= ES_PASSWORD : styleValue &= ~ES_PASSWORD;
        ::SetWindowLong(m_pWindow->GetHWND(), GWL_STYLE, styleValue);
    }
}

bool EditUI::IsPasswordMode() const
{
    return m_bPasswordMode;
}

void EditUI::SetPasswordChar(TCHAR cPasswordChar)
{
    if( m_cPasswordChar == cPasswordChar ) return;
    m_cPasswordChar = cPasswordChar;
    if( m_pWindow != NULL ) Edit_SetPasswordChar(m_pWindow->GetHWND(), m_cPasswordChar);
    Invalidate();
}

TCHAR EditUI::GetPasswordChar() const
{
    return m_cPasswordChar;
}

void EditUI::SetNativeEditBkColor(DWORD dwBkColor)
{
    m_dwEditbkColor = dwBkColor;
}

DWORD EditUI::GetNativeEditBkColor() const
{
    return m_dwEditbkColor;
}

void EditUI::SetNativeEditTextColor( LPCTSTR pStrColor )
{
    if( *pStrColor == _T('#')) pStrColor = ::CharNext(pStrColor);
    LPTSTR pstr = NULL;
    DWORD clrColor = _tcstoul(pStrColor, &pstr, 16);

    m_dwEditTextColor = clrColor;
}

DWORD EditUI::GetNativeEditTextColor() const
{
    return m_dwEditTextColor;
}

void EditUI::SetTextStyle(UINT uStyle)
{
    m_uTextStyle = uStyle;
    this->Invalidate();
}

UINT EditUI::GetTextStyle() const
{
    return m_uTextStyle;
}

void EditUI::SetPos(RECT rc, bool bNeedInvalidate)
{
    __super::SetPos(rc);
    if( m_pWindow != NULL ) {
        RECT rcPos = m_pWindow->CalPos();
        ::SetWindowPos(m_pWindow->GetHWND(), NULL, rcPos.left, rcPos.top, rcPos.right - rcPos.left, 
            rcPos.bottom - rcPos.top, SWP_NOZORDER | SWP_NOACTIVATE);        
    }
}

void EditUI::SetVisible(bool bVisible)
{
    __super::SetVisible(bVisible);
    if( !IsVisible() && m_pWindow != NULL ) m_pWindow->SetFocus(NULL);
}

void EditUI::SetInternVisible(bool bVisible)
{
    if( !IsVisible() && m_pWindow != NULL ) m_pWindow->SetFocus(NULL);
}

void EditUI::SetAttribute(const std::wstring& strName, const std::wstring& strValue)
{
    if(strName == _T("readonly")) SetReadOnly(strValue == _T("true"));
    else if(strName ==  _T("numberonly")) SetNumberOnly(strValue == _T("true"));
    else if(strName ==  _T("password")) SetPasswordMode(strValue == _T("true"));
    else if (strName == _T("passwordchar"))
    {
        LPCTSTR pValue = strValue.c_str();
        SetPasswordChar(*pValue);
    }
    else if(strName ==  _T("maxchar")) SetMaxChar(_ttoi(strValue.c_str()));
    else if(strName ==  _T("lowercase")) SetLowerCase(strValue == _T("true"));
    else if(strName ==  _T("uppercase")) SetUpperCase(strValue == _T("true"));
    else if (strName == L"caretcolor") {
        LPCTSTR pValue = strValue.c_str();
        while (*pValue > _T('\0') && *pValue <= _T(' ')) pValue = ::CharNext(pValue);
        SetCaretColor(pValue);
    }
    else if (strName == _T("promptmode")) {
        if (strValue == _T("true"))
            m_bAllowPrompt = true;
    }
    else if (strName == _T("promptcolor")) {
        LPCTSTR pValue = strValue.c_str();
        while (*pValue > _T('\0') && *pValue <= _T(' ')) pValue = ::CharNext(pValue);
        m_sPromptColor = pValue;
    }
    else if (strName == _T("prompttext")) SetPromptText(strValue);
    else if (strName == _T("font")) SetFont(strValue);
    else if (strName == _T("text")) SetText(strValue.c_str());
    else if (strName == _T("textpadding")) {
        UiRect rcPadding;
        LPTSTR pstr = NULL;
        rcPadding.left = _tcstol(strValue.c_str(), &pstr, 10);  ASSERT(pstr);
        rcPadding.top = _tcstol(pstr + 1, &pstr, 10);    ASSERT(pstr);
        rcPadding.right = _tcstol(pstr + 1, &pstr, 10);  ASSERT(pstr);
        rcPadding.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
        SetTextPadding(rcPadding);
    }
    //else if(strName ==  _T("nativetextcolor")) SetNativeEditTextColor(pstrValue);
    /*else if(strName ==  _T("nativebkcolor")) {
        if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
        LPTSTR pstr = NULL;
        DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
        SetNativeEditBkColor(clrColor);
    }*/
    else __super::SetAttribute(strName, strValue);
}

void EditUI::SetPromptMode(bool bPrompt)
{
    if (bPrompt == m_bAllowPrompt)
        return;
    m_bAllowPrompt = bPrompt;
    Invalidate();
}

std::wstring EditUI::GetPromptText() const
{
    return m_sPromptText;
}

void EditUI::SetPromptText(const std::wstring& strText)
{
    if (m_sPromptText == strText) return;
    m_sPromptText = strText;

    Invalidate();
}

BOOL EditUI::CreateCaret(INT xWidth, INT yHeight)
{
    m_iCaretWidth = xWidth;
    m_iCaretHeight = yHeight;
    return true;
}

BOOL EditUI::ShowCaret(BOOL fShow)
{
    if (fShow) {
        m_bIsCaretVisiable = true;
        m_drawCaretFlag.Cancel();
        std::function<void()> closure = nbase::Bind(&EditUI::ChangeCaretVisiable, this);
        TimerManager::GetInstance()->AddCancelableTimer(m_drawCaretFlag.GetWeakFlag(), closure, 500, TimerManager::REPEAT_FOREVER);
    }
    else {
        m_bIsCaretVisiable = false;
        m_drawCaretFlag.Cancel();
    }

    Invalidate();
    return true;
}

void EditUI::SetCaretColor(const std::wstring& dwColor)
{
    m_sCaretColor = dwColor;
}

std::wstring EditUI::GetCaretColor()
{
    return m_sCaretColor;
}

RECT EditUI::GetCaretRect()
{
    RECT rc = { m_iCaretPosX, m_iCaretPosY, m_iCaretPosX + m_iCaretWidth, m_iCaretPosY + m_iCaretHeight };
    return rc;
}

BOOL EditUI::SetCaretPos(INT x, INT y)
{
    m_iCaretPosX = x;
    m_iCaretPosY = y;
    //ShowCaret(GetSelText().empty());

    return true;
}

void EditUI::ChangeCaretVisiable()
{
    m_bIsCaretVisiable = !m_bIsCaretVisiable;
    Invalidate();
}

void EditUI::PaintCaret(IRenderContext* pRender, const UiRect& rcPaint)
{
    if (m_bReadOnly && m_bNoCaretReadonly)
        return;

    if (m_bIsCaretVisiable) {
        UiRect rect(m_iCaretPosX, m_iCaretPosY, m_iCaretPosX, m_iCaretPosY + m_iCaretHeight);
        DWORD dwClrColor = 0xff000000;

        if (!m_sCaretColor.empty())
            dwClrColor = this->GetWindowColor(m_sCaretColor);

        pRender->DrawLine(rect, m_iCaretWidth, dwClrColor);
    }
}
void EditUI::SetNoCaretReadonly()
{
    m_bNoCaretReadonly = true;
}

void EditUI::PaintChild(IRenderContext* pRender, const UiRect& rcPaint)
{
    UiRect rcTemp;
    if (!::IntersectRect(&rcTemp, &rcPaint, &m_rcItem)) return;

    PaintCaret(pRender, rcPaint);
}

void EditUI::PaintPromptText(IRenderContext* pRender)
{
    if (m_sText.size() != 0)
        return;

    if (!m_pWindow)
        return;

    std::wstring strPrompt = GetPromptText();
    if (strPrompt.empty() || m_sPromptColor.empty())
        return;

    UiRect rc = this->m_rcItem;
    rc.left += m_rcTextPadding.left;
    rc.right -= m_rcTextPadding.right;
    rc.top += m_rcTextPadding.top;
    rc.bottom -= m_rcTextPadding.bottom;

    DWORD dwClrColor = this->GetWindowColor(m_sPromptColor);
    UINT dwStyle = DT_NOCLIP;
    pRender->DrawText(rc, strPrompt, dwClrColor, m_sFontId, dwStyle, 255, false, false, IsD2DRender());
}

void EditUI::PaintStatusImage(IRenderContext* pRender)
{
    if (IsFocused()) {
        PaintPromptText(pRender);
        return;
    }
    __super::PaintStatusImage(pRender);
    PaintPromptText(pRender);
}

void EditUI::PaintText(IRenderContext* pRender)
{
    if (GetText().empty()) return;

    std::wstring sDrawText = GetText();
    if (m_bPasswordMode)
    {
        std::wstring sTemp = sDrawText;
        sDrawText.empty();
        LPCTSTR pStr = sTemp.c_str();
        while (*pStr != _T('\0')) {
            sDrawText += m_cPasswordChar;
            pStr = ::CharNext(pStr);
        }
    }

    //if (m_bSingleLine)
    //  m_uTextStyle |= DT_SINGLELINE;
    //else
        m_uTextStyle &= ~DT_SINGLELINE;

    ui::UiRect rc = m_rcItem;
    rc.left += m_rcTextPadding.left;
    rc.right -= m_rcTextPadding.right;
    rc.top += m_rcTextPadding.top;
    rc.bottom -= m_rcTextPadding.bottom;

    DWORD dwClrColor = this->GetWindowColor(m_sPromptColor);

    pRender->DrawText(rc, GetText(), dwClrColor, m_sFontId, m_uTextStyle, 255, false, false, IsD2DRender());
}

}

`