DuiLib : 限制CRichEditUI输入的Demo

如果只用 CRichEditUI.SetLimitText, 对输入的限制不是很好。


前几天做了一个richEdit输入控制.


需求 :

 * 只在richEdit中输入文本, 包含英文和中文.

 * 要求有最大字数限制(百十来字).

 * 不允许有回车

 * 允许RichEdit默认的copy, cut, paste.

 * 对剩余输入字数有统计和显示.

 * 字符数输入多时,不允许出现RichEdit默认的滚动条.


实现 :

  在WndMessageProc::WM_CHARDuiLib::Notify中处理字符输入的过滤,统计,显示.

  实现起来,比较简洁.  适用于字数较少的情况。


效果图:



工程下载 : 

srcRichEditLimit.rar


vs2010 vc++ + DuiLib-v391改版.


实现概览:

/// @file		MainDlg.h
/// @brief		主窗体

#ifndef __MAIN_DLG_H__
#define __MAIN_DLG_H__

#include "XmlWnd.h"

class CMainDlg : public CXmlWnd
{
public:
	CMainDlg(WCHAR * pcXmlFileName, WCHAR * pcWndClassName);
	virtual ~CMainDlg();

    DUI_DECLARE_MESSAGE_MAP()
    virtual void InitWindow();
    virtual void OnClick(TNotifyUI& msg);
    virtual void Notify(TNotifyUI & msg);
    virtual void OnFinalMessage(HWND hWnd);
    virtual LRESULT WndMessageProc(UINT uMsg, WPARAM wParam, LPARAM lParam);

private:
    void DataInit();
    void UiInit_richEdit();
    std::wstring GetStringInputLeft();
    int GetInputLeft();
    void CheckUploadInput();
    
private:
    DuiLib::CRichEditUI *   m_pRicheditInput; ///< 输入区
    DuiLib::CLabelUI *      m_pLabelLeftWordInd; ///< 剩余字符指示
    DuiLib::CButtonUI *     m_pBtnOk;
    DuiLib::CButtonUI *     m_pBtnCancel;
};

#endif // #ifndef __MAIN_DLG_H__

/// @file		MainDlg.cpp

#include "stdafx.h"
#include "MainDlg.h"

#define RICH_EDIT_INPUT_CHAR_MAX 70
#define DEFAUT_CONTENT L"请输入内容, 用于测试richEdit的限制输入字符串长度"

DUI_BEGIN_MESSAGE_MAP(CMainDlg, CXmlWnd)
DUI_END_MESSAGE_MAP()

CMainDlg::CMainDlg(WCHAR * pcXmlFileName, WCHAR * pcWndClassName)
    : CXmlWnd(pcXmlFileName, pcWndClassName)
{
    DataInit();
}

CMainDlg::~CMainDlg()
{
}

void CMainDlg::InitWindow()
{
    CenterWindow();
    UiInit_richEdit();

    m_pBtnOk = (CButtonUI *)m_PaintManager.FindControl(L"Button_done_ok");
    ASSERT(NULL != m_pBtnOk);

    m_pBtnCancel = (CButtonUI *)m_PaintManager.FindControl(L"Button_done_quit");
    ASSERT(NULL != m_pBtnCancel);

    m_pBtnOk->SetFocus(); ///< 让richdedit失去焦点, 显示默认的提示信息
}

void CMainDlg::DataInit()
{
    m_pRicheditInput = NULL;
    m_pLabelLeftWordInd = NULL;
    m_pBtnOk = NULL;
    m_pBtnCancel = NULL;
}

void CMainDlg::UiInit_richEdit()
{
    CHARFORMAT2             cfText;
    std::wstring            strTemp = L"";

    m_pRicheditInput = (CRichEditUI *)m_PaintManager.FindControl(L"richedit_input");
    ASSERT(NULL != m_pRicheditInput);

    m_pLabelLeftWordInd = (CLabelUI *)m_PaintManager.FindControl(L"LabelWordLeftInd");
    ASSERT(NULL != m_pLabelLeftWordInd);

    /// 设置richEdit
    m_pRicheditInput->EnableScrollBar(false, false);
    m_pRicheditInput->SetLimitText(RICH_EDIT_INPUT_CHAR_MAX * 2);
    m_pRicheditInput->SetReadOnly(false);

    ZeroMemory(&cfText, sizeof(CHARFORMAT));

    /// 当美工资源背景行的格子高度不同时,为了使字体输出和背景吻合, 
    /// 调整措施如下:
    /// * 移动"RichEdit控件容器的位置"
    /// * 调整字体大小
    /// * 调整字体Y方向偏移
    cfText.cbSize = sizeof(cfText);
    cfText.dwMask = CFM_SIZE | CFM_OFFSET;
    cfText.yHeight = 13*13; ///< 字体高度
    cfText.yOffset = 112;   ///< 行的Y方向偏移 
    m_pRicheditInput->SetDefaultCharFormat(cfText);

    m_pRicheditInput->SetAttribute(_T("textcolor"),_T("#222222"));
    m_pRicheditInput->SetSel(-1, -1);
    m_pRicheditInput->ReplaceSel(DEFAUT_CONTENT, false);

    /// 设置Label
    strTemp = ns_base::StringFormatV(L"还可输入%d个字", RICH_EDIT_INPUT_CHAR_MAX);
    m_pLabelLeftWordInd->SetText(strTemp.c_str());
}

void CMainDlg::OnClick(TNotifyUI& msg)
{
    std::wstring    strCtrlName = L"";

    if (NULL == msg.pSender)
        return;

    strCtrlName = msg.pSender->GetName();
    if (L"Button_done_ok" == strCtrlName)
    {
        // ok to quit
        ::PostMessageW(this->GetHWND(), WM_CLOSE, 0, 0);
    }
    else if (L"Button_done_quit" == strCtrlName)
    {
        // cancel to quit
        ::PostMessageW(this->GetHWND(), WM_CLOSE, 0, 0);
    }

    __super::OnClick(msg);
}

void CMainDlg::Notify(TNotifyUI & msg)
{
    std::wstring    strTemp = L"";

    if (msg.pSender == m_pRicheditInput)
    {
        strTemp = m_pRicheditInput->GetText();
        if (msg.sType == _T("setfocus"))
        {
            if (0 == strTemp.compare(DEFAUT_CONTENT))
            {
                m_pRicheditInput->SetText(L"");
            }

            m_pRicheditInput->SetAttribute(_T("textcolor"),_T("0"));
        }
        else if (msg.sType == _T("killfocus"))
        {
            if ((strTemp.size() <= 0)
                || (0 == strTemp.compare(DEFAUT_CONTENT)))
            {
                m_pRicheditInput->SetAttribute(_T("textcolor"),_T("#222222"));
                m_pRicheditInput->SetText(DEFAUT_CONTENT);
            }
            else
            {
                m_pRicheditInput->SetAttribute(_T("textcolor"),_T("0"));
            }
        }
        else if (msg.sType == DUI_MSGTYPE_TEXTCHANGED)
        {
            /// richedit 不进这里
        }

        m_pLabelLeftWordInd->SetText(GetStringInputLeft().c_str());
    }

    __super::Notify(msg);
}

void CMainDlg::OnFinalMessage(HWND hWnd)
{
    m_PaintManager.FreeResourceZip(); ///< ! guard memory leak
    __super::OnFinalMessage(hWnd);
    delete this;
}

std::wstring CMainDlg::GetStringInputLeft()
{
    std::wstring strOut = L"";

    strOut = ns_base::StringFormatV(L"还可以输入%d字", GetInputLeft());

    return strOut;
}

int CMainDlg::GetInputLeft()
{
    USES_CONVERSION;
    int iInputLeft = 0;
    int iLenMb = 0; ///< MultiByte length
    std::wstring strContent = L"";
    int iLenUnicode = 0;

    m_pRicheditInput->Invalidate();
    strContent = m_pRicheditInput->GetText();
    iLenUnicode = _tcslen(strContent.c_str());

    // convert an widechar string to Multibyte   
    iLenMb = WideCharToMultiByte(CP_ACP, 0, strContent.c_str(), iLenUnicode, NULL, 0, NULL, NULL);  
    iInputLeft = m_pRicheditInput->GetLimitText() - iLenMb;
    if (iInputLeft < 0)
    {
        iInputLeft = 0;
    }

    return iInputLeft;
}

LRESULT CMainDlg::WndMessageProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CHAR:
        {
            if (m_pRicheditInput->IsFocused())
            {
                CheckUploadInput();
                m_pLabelLeftWordInd->SetText(GetStringInputLeft().c_str());
            }
        }
        break;

    default:
        break;
    }

    return __super::WndMessageProc(uMsg, wParam, lParam);
}

void CMainDlg::CheckUploadInput()
{
    std::wstring strContent = L"";
    std::wstring strContentCheck = L"";
    int iLenUnicode = 0;
    int iLenMb = 0;

    strContent = m_pRicheditInput->GetText();
    ns_base::RemoveEnterChar(strContent, strContentCheck);
    if (strContent != strContentCheck)
    {
        strContent = strContentCheck;
        m_pRicheditInput->SetText(strContent.c_str());
    }

    iLenUnicode = _tcslen(strContent.c_str());

    // convert an widechar string to Multibyte   
    iLenMb = WideCharToMultiByte(CP_ACP, 0, strContent.c_str(), iLenUnicode, NULL, 0, NULL, NULL);
    if (iLenMb > m_pRicheditInput->GetLimitText())
    {
        while (1)
        {
            iLenUnicode = _tcslen(strContent.c_str());
            iLenMb = WideCharToMultiByte(CP_ACP, 0, strContent.c_str(), iLenUnicode, NULL, 0, NULL, NULL);
            if (iLenMb > m_pRicheditInput->GetLimitText())
            {
                strContent = strContent.substr(0, strContent.size() - 1);
                continue;
            }

            m_pRicheditInput->SetText(strContent.c_str());
            break;
        }
    }
}





 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值