CRichEditView text formatting

ok, I'm trying to change the format of the text in a CRichEditView...nothing fancy, I'd just like to set the tabs to a width of 4 characters and to change the font to a user specified font, which is represented as the CFont variable "currfont." Here's what I have so far:

Obviously, it doesn't bold the text, even with "bold" selected (although it would be nice if it would), but most perplexing is that it won't change the text size and the tabs are completely screwed up. Any idea how to change this so it works?

-W.W.
P.S. The text should not be able to change color...i.e. it should be plain black.

You're not setting the tab stops correctly--you don't understand how tab stops in the control work.

The control lets you specify tab stop positions in twips, not in character columns. The control may display proportional width fonts, so it's impossible to know that a tab stop happens every nth character unless you also know that you're using a monospace font.

If you're using a monospace font and want to have the tabstops at every 4th character, you'll need to do some conversions to get the right values for the tabstops array. Your code above already gets the LOGFONT for your font, and that has an lfWidth member which shows the average width of a character in the font in pixels on the device where the font's selected.

Assuming your font is selected into a display device, you can get the ratio between horizontal pixels and inches by asking the GetDeviceCaps() function for LOGPIXELSX. So, that might look like:

HDC hdc = ::GetDC();
int nPixels = ::GetDeviceCaps(hdc, LOGPIXELSX);

Then, since you now know that there are nPixels for each inch on your display, and you know that there are 1440 twips per inch, you can get the number of twips for the width of the characters in your font with this expression:

OK, couple of problems here, the first and foremost being that the above code doesn't work, mostly because the lfWidth of the LOGFONT struct is always 0. The second problem is that you didn't even address how to change the size of the font...lfHeight is always a negative number which has little to do with the font size...help me out here.

Font height can be negative - it means you are specifying char height instead of cell height. it can bne zero as well, which means use a sensible default.

Font width can be zero - it means to calculate the width from the height based on aspect ratios etc

So GetLogFont may well be returning the correct values anyway.

SetFont won't select it into the DC - it just sets what the default font will be for that window when a dc is created. It is SelectObject that selects a font into a DC

To get the average char width, why not just use GetTextMetric after selecting the font into the DC with SelectObject ?

PS: in general code like
CHARFORMAT cf;
memset(&cf, 0, sizeof(cf));
is not nice (and sometimes unsafe) in C++ (when classes may have vtables and references etc) .. maybe you could just try
CHARFORMAT cf = {0};

Seeing as how CHARFORMAT is a struct and not a class, I don't see anything wrong with the above code. In any case, Using GetTextMetric returns a number from 9-11 as the average width...now what? The equation mentioned earlier (e.g. tabwidth = LOGPIXELSX * fontwidth / 1440) doesn't work since the resulting answer always comes out to be less than one.

It's not bad programming practice as there's nothing wrong with calling memset() on a struct. struct's aren't equivalent to classes, especially the way you're measuring them here: a struct can't have virtual functions.

Even when a class does have virtual functions, using memset() on a pointer to the class for sizeof(theclass) sets the member data, not the vtable.

Good programming practice isn't a waste of breath, but dubious advice certainly is.

I am smply answering the invalid criticisms Mike made of my advice to (in general) not use memset of classes and structs

Unless you are sure that the class/struct does NOT have virtual functions or constructors, and if it contains or derives from other classes/structs that these also satisfy this requirement. (ie. it should be an "aggregate").

In such a case then it is safe to use a memset, BUT it is safer to use an initializer when defining the struct variable. An initializer will not compile if the struct is NOT an aggregate (protecting yourself from errors), whereas memset will clobber anything it is given).

I know that the answer has been given and these points are not directly relevant to the question. However, this thread will remain in the PAQ and I would not like to see someone read this and go away believing that memset's are always safe with structs and cannot clobber vtable pointers in classes when that is simply NOT the case.

Unions cannot be derived from, nor can they dervie from a class or struct). Unions cannot have virtual functions (although they can still have member functions including constructors and destructors - unless anonymous).

Introduction:
The undo support, implementing a stack.
Continuing from the eigth article about sudoku.
We need a mechanism to keep track of the digits entered so as to implement an undo mechanism. This should be a ‘Last In First Out’ collec…

Introduction:
Dialogs (1) modal - maintaining the database.
Continuing from the ninth article about sudoku.
You might have heard of modal and modeless dialogs. Here with this Sudoku application will we use one of each type: a modal dialog …

Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…