2

我在 MFC 项目中有一个 CRichEditCtrl,我将其用作报告日志。根据给定的情况,我需要将不同颜色的文本附加到控件(即标准通知的蓝线,错误的红线等)。我已经非常接近让它工作了,但它仍然表现得很奇怪:

void CMyDlg::InsertText(CString text, COLORREF color, bool bold, bool italic)
{
    CHARFORMAT cf = {0};
    CString txt;
    int txtLen = m_txtLog.GetTextLength();
    m_txtLog.GetTextRange(0, txtLen, txt);

    cf.cbSize = sizeof(cf);
    cf.dwMask = (bold ? CFM_BOLD : 0) | (italic ? CFM_ITALIC : 0) | CFM_COLOR;
    cf.dwEffects = (bold ? CFE_BOLD : 0) | (italic ? CFE_ITALIC : 0) |~CFE_AUTOCOLOR;
    cf.crTextColor = color;

    m_txtLog.SetWindowText(txt + (txt.GetLength() > 0 ? "\n" : "") + text);
    m_txtLog.SetSel(txtLen, m_txtLog.GetTextLength());
    m_txtLog.SetSelectionCharFormat(cf);
}

充其量,最终结果是新附加的行被适当地着色,但所有先前的文本都变成黑色。最重要的是,对于每个附加的文本行,起始选择似乎增加了 1。例如:

Call #1:
- [RED]This is the first line[/RED]

Call #2:
- [BLACK]This is the first line[/BLACK]
- [GREEN]This is the second line[/GREEN]

Call #3:
- [BLACK]This is the first line[/BLACK]
- [BLACK]This is the second line[/BLACK]
- [BLUE]This is the third line[/BLUE]

Call #4:
- [BLACK]This is the first line[/BLACK]
- [BLACK]This is the second line[/BLACK]
- [BLACK]This is the third line[/BLACK]
- [BLACK]T[/BLACK][YELLOW]his is the fourth line[/YELLOW]

Call #5:
- [BLACK]This is the first line[/BLACK]
- [BLACK]This is the second line[/BLACK]
- [BLACK]This is the third line[/BLACK]
- [BLACK]This is the fourth line[/BLACK]
- [BLACK]Th[/BLACK][ORANGE]is is the fifth line[/ORANGE]

etc...

那么我该如何解决这个问题,让所有以前的文本和格式保持原样,同时附加一行新的彩色文本呢?

4

3 回答 3

6

您的示例代码通过调用从对话框中读取旧文本GetTextRange()。这不包括任何丰富的格式,因此,当文本放回原位时,它不会被格式化。您可以通过将光标设置到末尾而无需任何选择并调用ReplaceSel().

我认为你的方法应该是这样的:

void CMFCApplication2Dlg::InsertText(CString text, COLORREF color, bool bold, bool italic)
{
    CHARFORMAT cf = {0};
    int txtLen = m_txtLog.GetTextLength();

    cf.cbSize = sizeof(cf);
    cf.dwMask = CFM_BOLD | CFM_ITALIC | CFM_COLOR;
    cf.dwEffects = (bold ? CFE_BOLD : 0) | (italic ? CFE_ITALIC : 0);
    cf.crTextColor = color;

    m_txtLog.SetSel(txtLen, -1); // Set the cursor to the end of the text area and deselect everything.
    m_txtLog.ReplaceSel(text); // Inserts when nothing is selected.

    // Apply formating to the just inserted text.
    m_txtLog.SetSel(txtLen, m_txtLog.GetTextLength());
    m_txtLog.SetSelectionCharFormat(cf);
}
于 2012-12-01T03:39:09.440 回答
0

在插入新文本之前指定格式。如果您在插入后应用格式,您最终会得到格式不正确的文本。

CHARFORMAT cf = { 0 };
int txtLen =  GetTextLength();

cf.cbSize = sizeof(cf);
cf.dwMask = CFM_COLOR;
cf.dwEffects = ~CFE_AUTOCOLOR;//No auto color
cf.crTextColor = RGB(0, 0, 255);//color of the text

SetSel(txtLen, -1);//Deselect all
SetSelectionCharFormat(cf);//Assign the format to the cursor pos
ReplaceSel(newText);
于 2019-10-18T23:58:28.857 回答
0

我从试图让它工作中学到的东西是,你不能像上面的例子那样设置标志。这样做:

 cf.dwMask = (bold ? CFM_BOLD : 0) | (italic ? CFM_ITALIC : 0) | CFM_COLOR;

一半有效,但是如果您使用 CRichEditCtrl (作为示例)并获取当前格式(尽管我认为这对我来说无论如何都会发生......)问题是上面的标志是设置要切换的值。所以,这实际上更有效:

CHARFORMAT cf;
cf.cbSize = sizeof(CHARFORMAT);
GetSelectionCharFormat(cf);

cf.dwMask = CFM_BOLD | CFM_ITALIC | CFM_COLOR; //set these to specify the flags you are changing

if (bold)
{
    cf.dwEffects |= CFE_BOLD; //toggle on
}
else
{
    cf.dwEffects &= ~CFE_BOLD; //toggle off
}

if (italic)
{
    cf.dwEffects |= CFE_ITALIC; //toggle on
}
else
{
    cf.dwEffects &= ~CFE_ITALIC; //toggle off
}

cf.dwEffects &= ~CFE_AUTOCOLOR; //this only seemed to work if I set it this way

如果您不这样做,格式将保留 - 即使您已清除它。这让我挠了挠头,我做了很多谷歌搜索来修复它。

于 2018-09-20T13:47:58.673 回答