tags:

views:

643

answers:

3

Problem: How can I tell if a selection of text in the CRichEditCtrl has multiple font sizes in it?


Goal: I am sort of making my own RichEdit toolbar (bold, italic, font type, font size, etc). I want to emulate what MS Word does when a selection of text has more than a single font size spanning the selection.

Ex - You have a line of text with the first 10 characters 9 pt font and the next 15 characters 14 pt font. If you highlight the first 5 characters, the "Font Pt Selection" drop down displays "9". If you then select the first 20 characters, the same drop down should have a empty/blank display.


What I have going so far: I am getting the necessary notification when the selection changes inside of the CRichEditCtrl. Also, if there is only a single font size in the selection I am able to figure that out

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

This will give me the needed info for the first case of my example above. Unfortunately, what I seem to get for the second part of my example only gives me back the info for where the selection ends (instead of the entire selection).

In conclusion, is there some info I am missing in the CHARFORMAT or some other struct I can get from the CRichEditCtrl or some kind of interesting calculation I can do to make the decision that there are multiple sizes in the selection? So far my only idea is to chug through the selection a character at a time and see if the current font size of that character is different than any of the previous characters. I am mostly just hoping the info I need is there, and I just don't see it (In a similar way that from the CHARFORMAT's dwMask member tells me that any or all of Bold, Italic, Underline, etc are turned on).

A: 

I don't know the answer, but you could also try digging around in the ITextDocument documentation, which is a somewhat fuller interface to a rich edit control. I think you can obtain an ITextDocument from a rich edit by using EM_GETOLEINTERFACE.

thudbang
+1  A: 

As the above answer notes, the easiest way I can think of to do this is to use the Text Object Model (TOM), which is accessed through the ITextDocument COM interface. To get at this from your rich edit control (note code not tested, but should work):

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

Then get a range. Here this is for the selected text, but one of the advantages of TOM is that you can operate on any range, not just what's selected.

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

Then get the font for the range, and see what its characteristics are, e.g.

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

If the range is formatted with a single font size, you'll get that back in "size". If there's multiple font sizes, you'll get the value "tomUndefined" instead.

DavidK
A: 

Thanks for both of your answers!

Been juggling a couple things, but I was finally able to work at it thanks to both of your responses. This is how I finally was able to get everything to compile and run:

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;

Once again, thanks a lot to both of you. I find it hard to believe I would have gone down that path.

Scott

Scott