(转)Q版MSN-仿QQ聊天内容显示 - CRichEditCtrl

来源:互联网 发布:书生软件转换工具 编辑:程序博客网 时间:2024/05/22 00:24

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

原创粉丝点击