如何确定CRichEditCtrl中所选文本是否具有多种字体大小

How do I decide if a selection of text in CRichEditCtrl has multiple font sizes?

本文关键字:字体 是否 CRichEditCtrl 何确定 文本      更新时间:2023-10-16

问题:如何判断CRichEditCtrl中选择的文本中是否有多个字体大小?


目标:我正在制作自己的RichEdit工具栏(粗体、斜体、字体类型、字体大小等)。我想模仿MS Word在所选文本中有多个字体大小时所做的操作。

例如,您有一行文本,前10个字符为9磅字体,后15个字符为14磅字体。如果突出显示前5个字符,"字体点选择"下拉菜单将显示"9"。如果随后选择前20个字符,则相同的下拉列表应显示空/空白。


到目前为止我所做的:当CRichEditCtrl内部的选择发生更改时,我收到了必要的通知。此外,如果选择中只有一个字体大小,我可以计算出

CHARFORMAT cf;
cf.cbSize = sizeof(CHARFORMAT);
CRichEditCtrl ctrl;
ctrl.GetSelectionCharFormat( cf );
int nFontPtSize = cf.yHeight / 20;

这将为我提供上面例子的第一个案例所需的信息。不幸的是,我在示例的第二部分中得到的信息似乎只给了我选择结束的信息(而不是整个选择)。

总之,我在CHARFORMAT中是否缺少一些信息,或者我可以从CRichEditCtrl中获得的其他结构,或者我能做一些有趣的计算来决定选择中有多个大小?到目前为止,我唯一的想法是一次选择一个字符,看看这个字符的当前字体大小是否与以前的任何字符都不同。我主要只是希望我需要的信息在那里,但我看不到它(就像CHARFORMAT的dwMask成员告诉我任何或所有粗体、斜体、下划线等都打开了一样)。

正如上面的答案所指出的,我能想到的最简单的方法是使用文本对象模型(TOM),它可以通过ITextDocument COM接口访问。要从富编辑控件中获得这一点(请注意,代码没有经过测试,但应该可以工作):

CComPtr<IRichEditOle> richOle;
richOle.Attach(edit.GetIRichEditOle());
CComQIPtr<ITextDocument> textDoc(richOle);

然后得到一个范围。这是针对所选文本的,但TOM的优点之一是可以对任何范围进行操作,而不仅仅是对所选内容进行操作。

CComPtr<ITextSelection> range;
textDoc->GetSelection(&range);

然后获取范围的字体,并查看其特征,例如

CComPtr<ITextFont> font;
range->GetFont(&font);
long size;
font->GetSize(&size);

如果该范围的格式是单一的字体大小,你会得到"大小"。如果有多个字体大小,您将得到值"tomUndefined"。

我一直在处理一些事情,但我终于能够工作了。这就是我最终能够编译和运行一切的方式:

HWND hwnd;
ITextDocument* pDoc;
IUnknown* pUnk = NULL;
float size = 0;
hwnd = GetSafeHwnd();
::SendMessage( hwnd, EM_GETOLEINTERFACE, 0, (LPARAM)&pUnk );
   if ( pUnk && pUnk->QueryInterface( __uuidof(ITextDocument), (void**)&pDoc ) == NOERROR )
   {
      CComPtr<ITextSelection> range;
      pDoc->GetSelection( &range );
      CComPtr<ITextFont> font;
      range->GetFont( &font );     
      // If there are multiple font sizes in the selection, "size" comes back as -9999 
      font->GetSize(&size);
   }
return size;