Q版MSN-仿QQ聊天内容显示 - CRichEditCtrl
作者:张国斌
今天在写Q版MSN的聊天内容显示界面,以前虽写过不少代码,但大部分都是使用Delphi的RichEdit控件,从未用过VC中的CRichEditCtrl,在网络上搜索了半天也没找到一个现成的(找了一个好像是韩国人写的ExRichEdit,但他的代码有问题,大家可以下载下来测试一下就知道了。http://www.codeguru.com/cpp/controls/richedit/article.php/c2395),所以只能自已动手了,下面给大家分享一下QQ聊天内容中CRichEditCtrl显示代码。
主要包括以下几个方面:
1、时间及姓名不同颜色的显示
2、聊天内容的缩进
3、超链接的识别及响应
4、右键菜单及响应(这部分网络上材料比较多,所以我就不说了)
效果如下图所示:
不同颜色的显示,网络上大部分都是类似用下面的代码:
void AddText(LPCTSTR szTextIn, COLORREF &crNewColor)
{
int iTotalTextLength = GetWindowTextLength();
SetSel(iTotalTextLength, iTotalTextLength);
ReplaceSel(szTextIn);
int iStartPos = iTotalTextLength;
CHARFORMAT cf;
cf.cbSize = sizeof(CHARFORMAT);
cf.dwMask = CFM_COLOR | CFM_UNDERLINE | CFM_BOLD;
cf.dwEffects =(unsigned long) ~( CFE_AUTOCOLOR | CFE_UNDERLINE | CFE_BOLD);
cf.crTextColor = crNewColor;//RGB(0, 0, 0);
int iEndPos = GetWindowTextLength();
SetSel(iStartPos, iEndPos);
SetSelectionCharFormat(cf);
}
即先得到当前RichEdit中的内容长度,然后添加新的内容,再计算当前RichEdit中的内容长度,再SetSel(iStartPos, iEndPos);将新增的内容选中,SetSelectionCharFormat(cf);更改字体或颜色之类的。
原理上,上面的做法是正确的,可是不知道是不是CRichEditCtrl的bug,GetWindowTextLength();得到的长度跟实际的有偏差,所以选中的内容是不正确的。以下代码是本人查找多方面的资料并经过多次成功:
//1、时间及姓名不同颜色的显示
void CQMSNRichEdit::AddTitle(CString strTextIn, COLORREF crNewColor)
{
SendMessage(EM_SETSEL,-2, -1); //这行一定要,目的是将光标停到最后
//设置即将要显示的字体颜色
CHARFORMAT cf;
ZeroMemory(&cf, sizeof(CHARFORMAT));
cf.cbSize = sizeof(CHARFORMAT);
cf.dwMask = CFM_COLOR;
cf.crTextColor = crNewColor;
SetWordCharFormat(cf);
//恢愎缩进为0
PARAFORMAT2 pf2;
ZeroMemory(&pf2, sizeof(PARAFORMAT2));
pf2.cbSize = sizeof(PARAFORMAT2);
pf2.dwMask = PFM_STARTINDENT;
pf2.dxStartIndent = 0;
SetParaFormat(pf2);
SetSel(-1, -1);
ReplaceSel(strTextIn);
PostMessage(WM_VSCROLL, SB_BOTTOM, 0);//将滚动条滚到最后
}
//2、聊天内容的缩进
void CQMSNRichEdit::AddText(CString strTextIn, COLORREF crNewColor)
{
SendMessage(EM_SETSEL,-2, -1);
CHARFORMAT cf;
ZeroMemory(&cf, sizeof(CHARFORMAT));
cf.cbSize = sizeof(CHARFORMAT);
cf.dwMask = CFM_COLOR;
cf.crTextColor = crNewColor;
SetWordCharFormat(cf);
//设置缩进为200
PARAFORMAT2 pf2;
ZeroMemory(&pf2, sizeof(PARAFORMAT2));
pf2.cbSize = sizeof(PARAFORMAT2);
pf2.dwMask = PFM_STARTINDENT;
pf2.dxStartIndent = 200;
SetParaFormat(pf2);
SetSel(-1, -1);
ReplaceSel(strTextIn);
PostMessage(WM_VSCROLL, SB_BOTTOM, 0);
}
//3、超链接的识别及响应
void CQMSNRichEdit::PreSubclassWindow()
{
// TODO: 在此添加专用代码和/或调用基类
//设置初始字体
CHARFORMAT cf;
cf.cbSize = sizeof (CHARFORMAT);
cf.dwMask = CFM_COLOR|CFM_OFFSET|CFM_SIZE|CFM_FACE|CFM_CHARSET;
cf.yHeight = 180; //设置高度
cf.yOffset = 0;
cf.crTextColor=RGB(0,0,0);
cf.bCharSet = GB2312_CHARSET;
_tcscpy(cf.szFaceName, _T("宋体")); //设置字体
SetDefaultCharFormat(cf);
//设置自动识别链接
SetEventMask(ENM_LINK);
//支持超链接点击响应
PostMessage(EM_AUTOURLDETECT, TRUE, 0);
CRichEditCtrl::PreSubclassWindow();
}
//添加消息ON_NOTIFY_REFLECT(EN_LINK,OnURLClick)
BEGIN_MESSAGE_MAP(CQMSNRichEdit, CRichEditCtrl)
//{{AFX_MSG_MAP(CRichEditCtrlEx)
//}}AFX_MSG_MAP
ON_NOTIFY_REFLECT(EN_LINK,OnURLClick)
END_MESSAGE_MAP()
//下面编写消息响应函数 afx_msg void OnURLClick(NMHDR *pNmhdr, LRESULT *pResult);
void CQMSNRichEdit::OnURLClick(NMHDR *pNmhdr, LRESULT *pResult)
{
if(pNmhdr->code == EN_LINK)
{
ENLINK *pLink = (ENLINK *)pNmhdr;
if (pLink->msg == WM_LBUTTONDOWN)
{
SendMessage(EM_EXSETSEL, 0, (LPARAM)&(pLink->chrg));
OpenURL(GetSelText(), SW_SHOWNORMAL);
HideSelection(TRUE, TRUE);
}
}
pResult = FALSE;
}
//以下是OpenURL,代码是参考HYPERLINK中的打开网页部分
HINSTANCE CQMSNRichEdit::OpenURL(LPCTSTR url, int showcmd)
{
TCHAR key[MAX_PATH + MAX_PATH];
// First try ShellExecute()
HINSTANCE result = ShellExecute(NULL, _T("open"), url, NULL,NULL, showcmd);
// If it failed, get the .htm regkey and lookup the program
if ((UINT)result <= HINSTANCE_ERROR) {
if (GetRegKey(HKEY_CLASSES_ROOT, _T(".htm"), key) == ERROR_SUCCESS) {
lstrcat(key, _T("\\shell\\open\\command"));
if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS) {
TCHAR *pos;
pos = _tcsstr(key, _T("\"%1\""));
if (pos == NULL) { // No quotes found
pos = _tcsstr(key, _T("%1")); // Check for %1, without quotes
if (pos == NULL) // No parameter at all...
pos = key+lstrlen(key)-1;
else
*pos = '\0'; // Remove the parameter
}
else
*pos = '\0'; // Remove the parameter
lstrcat(pos, _T(" "));
lstrcat(pos, url);
result = (HINSTANCE) WinExec(LPCSTR(key),showcmd);
}
}
}
return result;
}
LONG CQMSNRichEdit::GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata)
{
HKEY hkey;
LONG retval = RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey);
if (retval == ERROR_SUCCESS) {
long datasize = MAX_PATH;
TCHAR data[MAX_PATH];
RegQueryValue(hkey, NULL, data, &datasize);
lstrcpy(retdata,data);
RegCloseKey(hkey);
}
return retval;
}
欢迎转载本博原创文字和图片,但请注明作者和出处!
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhanggb86/archive/2009/06/20/4285575.aspx