如果只用 CRichEditUI.SetLimitText, 对输入的限制不是很好。
前几天做了一个richEdit输入控制.
需求 :
* 只在richEdit中输入文本, 包含英文和中文.
* 要求有最大字数限制(百十来字).
* 不允许有回车
* 允许RichEdit默认的copy, cut, paste.
* 对剩余输入字数有统计和显示.
* 字符数输入多时,不允许出现RichEdit默认的滚动条.
实现 :
在WndMessageProc::WM_CHAR和DuiLib::Notify中处理字符输入的过滤,统计,显示.
实现起来,比较简洁. 适用于字数较少的情况。
效果图:
工程下载 :
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;
}
}
}