Resizing a CStatic control dynamically to fit text - c++

As of now, I'm using the following to code to resize my CStatic controls:
WINDOWPLACEMENT wndpl;
m_myStaticControl.GetWindowPlacement(&wndpl);
// Increase the static box's width
wndpl.rcNormalPosition.right += 10;
m_myStaticControl.SetWindowPlacement(&wndpl);
m_myStaticControl.SetWindowText("Some text");
I obtain the constant (in the above case, 10) by trial-and-error. Because this seems like a really inelegant and hard-to-maintain solution, I want to change this. After some research, I think I have a basic idea; which is:
Get the pixel width and height of the required text using GetTextExtentPoint32.
Get the current window placement of the CStatic control as in code example above.
If the current width < obtained pixel width, add obtained pixel width. Do the same for height.
Set the window placement as in code example above.
Set the window text as in code example above.
Would this be a good, efficient approach? Also, does GetTextExtentPoint32 use pixels or dialog units?

Related

Motif How to calculate or retrieve the font pixel size?

I am trying to write code in Motif to change a dialog warning box to resize size it if the box is not wide enough. The width and height is always being set by the calling classes and its not always wide enough for the message being displayed and the end of the line is truncated off. Instead of fixing everywhere to use auto sizing (i.e. width is 0 or not set at all) they want to figure out what the pixel width size is for a character in the dialog. They can then multiple the longest line X pixels width to get the lines length in pixels. Then we would see if the dialog declared width needs to be reset to stop the truncation. Only dialogs that are too short will be changed (dialogs too wide are not to be changed).
However; I can't find any example on how get the character width in pixels anywhere. I remember years ago I was on a project where they created some type of widget, inserted a character into it, and then did a XtGetValues to get the width and height so I think it can be done. So does anyone know how to do this?
That was a long time ago, but if memory serves, Xt doesn't have any specific support for fonts, it relies on plain libx11. You will need to call XQueryFont or XLoadQueryFont to get the XFontStruct describing your font, then grovel through the per_char array to find the extents of individual glyphs.

DirectWrite align text center

I am trying to align center the text I have to draw. I use ID2D1RenderTarget::DrawTextLayout method. The problemn is that if I set the text horizontal alignment to DWRITE_TEXT_ALIGNMENT_LEADING (the default value) the text is drawn proberly, but if I change this value to DWRITE_TEXT_ALIGNMENT_CENTER the text is shifted right.
The example string is
Internal Amazing
Scupper
Following are the outcomes (the first is alignment leading):
My comment as an answer (yeah, guessed right :)):
Just a quick guess: Did you check that the maxwidth your layout box
isn't too broad, so the center would end there at the right?
The IDWriteTextLayout used by ID2D1RenderTarget::DrawTextLayout method defines a maximum width of the layout box, which determines where the text is centered. It can be manipulated by the methods of the interface (GetMaxWidth and SetMaxWidth).
When you create the text layout, you cannot change the width and height to something greater afterwards. You should use max screen coords when creating the layout then change the max width and height to the desired size. You should use render_tgt->DrawText(...) method for this example or release and recreate the layout interface every time the text, font name, and a lot of other various things like typography are changed. I created an array of layout and typography events that can be reapplied to the layout interface every time it is recreated. You do not need to recreate the layout for font size, since you can resize the text or individual characters with the layout interface
// Set the layout to maximum screen size
FLOAT maxX = (FLOAT)GetSystemMetrics(SM_CXFULLSCREEN); // * XD2D::pix_to_dips.x;
FLOAT maxY = (FLOAT)GetSystemMetrics(SM_CYFULLSCREEN); // * XD2D::pix_to_dips.y;
XS_DWRITE_DEV_FACTORY->CreateTextLayout
(
dstring,
dlength,
(*pp_txt_format),
maxX,
maxY,
pp_txt_layout
);
// Resize to the requested size or minimum allowed size
(*pp_txt_layout)->SetMaxWidth(max(req_xsize, (*pp_txt_layout)->GetFontSize()));
(*pp_txt_layout)->SetMaxHeight(max(req_ysize, (*pp_txt_layout)->GetFontSize()));

Detect if MFC control has insufficient width to hold text (and text will be truncated)

MFC doesn't have layouts, so controls have to be fixed size and position.
When localizing for a new language, I edit the .rc files directly, but if the text for the new language is longer than the control's width will allow, it gets truncated.
This requires me to do manual inspection of each control to see if it has sufficient width, which is both time-consuming and error-prone.
Right now I'm thinking about adding some code to enumerate all controls, get their text, and see what its width would be, and compare that to the control's width.
Is there a better way?
Actually you can handle this by using following example of layout,
Layout Manager for Dialogs, Formviews, DialogBars and PropertyPages.Check the size of max text and re-arrange controls according to control.Hope it will work.

Vertical centering of multi-line cstatic text in MFC

How can one make a CStatic with text auto-wrap (multiline) which vertically centeres the result in the control's rectangle?
The problem I'm trying to solve is this: I have a CStatic control next to a CComboBox which updates information text depending on the choice. This text can be either short or long, requiring the CStatic to sometimes use multi-lines, and sometimes not. I want the info-text be vertically center-aligned with the CComboBox.
Now here is the problem:
If I make the CStatic only 1 textline high, it looks good for 1-line texts, but multi-lines do not fit and are not displayed.
If I make the CStatic higher to fit 2 lines, it looks good for long texts (with 2 lines), but 1-line-texts are shifted upwards, as the CStatic aligns the text on the top. A CStatic with the behavior mentioned in the question would solve this...
If I can't easily get a vertically centered CStatic multi-line control, the alternative would be to resize the control rect depending on the amount of text in it. But in this case I have a different problem:
How can I programatically find out how many lines a text will need in a CStatic of specific width?
Unfortunately you can't vcenter multi-line text in a CStatic.
Your next question has a solution but it's a bit of a pain to use. What you do is you use CDC::DrawTextEx with the DT_CALCRECT flag to get the size (in pixels) of the text you want to format. By dividing that by the height of a line of text (given in the font info you can get from the DC, plus some spacing which I'm not sure of how much that is - presumably it's a fixed amount, I don't think you can specify line spacing with DrawText), you will get (an approximation of) the number of lines you will get. You can then resize the control rect.
Come to think of it, you are probably better off not converting to lines and just resize your control to the extent you get from DrawTextEx :)
Things like this usually require some experimentation to get exactly right, and sometimes behave differently between OS versions. Proceed with caution.

How to combine two HICONs into one

I have one HICON which I want to use as an overlay on another HICON, to create a result HICON. The result HICON will then be used in an "owner draw" control (note: it doesn't use imagelists). The overlay icon has transparency color RGB(0, 255, 0).
How do I go about doing this in Native C++ (I've only found sources that show how to do this with managed code).
I generally agree with peterchen's answer, with some notes:
There's no reason to work with DIBs (unless you're synthesizing the image directly by altering its bits, rather than drawing using GDI functions).
You should keep in mind that GetIconInfo actually creates copies of the icon't bitmaps within your process. It's your responsibility to delete them when no more needed.
Unless you're going to pass the resulting HICON to either standard control or another process - there's just no need to create such. Instead it's better to work with a bitmap (and, possibly, mask).
It's important to understand the difference between icon and bitmap.
Bitmap is a GDI object. It's valid within your process.
Icon is a User object, and its scope is not limited to your process. It wraps a bitmap and, optionally, a mask.
There're several icon types:
The simplest, consisting of a single bitmap, which is drawn as-is.
Bitmap + mask, the mask marks solid/transparent pixels
32-bit bitmap, with alpha channel
Monochrome bitmap + mask. The bitmap + mask define the so-called AND-XOR operation (that is performed on the target surface).
So that after you get the contents of the icon (by GetIconInfo) you should discover the actual icon type, because each of those options requires different handling.
(1) overlay Icons
In many places of the windows API, there are overlay icons supported (e.g. ListView, and TreeView with help ofthe ImageList, also in the shell)
(2) As Hans says
The most straigtforward way would be to
create a memory DC on a bitmap
Draw the two icons on top of each other
create an icon from the bitmap
(3) if you insist
If you insist in doing it manually (though i see no reason to):
GetIconInfoto get the underlying bitmaps. Note that b&w icons need special treatment
GetObjectthe get the BITMAP for a HBITMAP. if you don't also insist on handling various bitmap formats, you should covnert them into DIB sections.
Do your magic