Calculate size of text (text rectangle) rendered with GDI - winapi

I'm trying to create a menu and draw it with GDI.
I have a MENU TITLE, unchangable.
I have an array of items.
If I want the title to be "MAIN MENU" how do I calculate the width and height of the Text? If I set SetBkColor() just before TextOut() to a different color than the HDC Background I see that it's rendered as a Rectangle - but how do I get the size of this rectangle and before writing out the Text on the screen?
Also, I set CreateFont() and SelectObject(HDC, Font) beforehand so I can write "bigger" text for the Menu.
Anyone with suggestions?
Haven't found a working solution for this with native GDI and not using newer Graphics objects in .NET.

The easiest way is probably DrawText() with DT_CALCRECT.
You can also measure text yourself with GetTextExtentPoint32().

Related

Draw themed combobox on windows

I try to emulate the look of a themed noneditable combobox (CBS_DROPDOWNLIST) using DrawThemeBackground. I supply the part CP_READONLY, which apparently draws the background of a themed combobox:
DrawThemeBackground(theme, dc, CP_READONLY, CBRO_NORMAL, &rectangle, nullptr);
However, it does not contain the dropdown arrow. So, I tried to paint the arrow myself the following way:
rectangle.left = rectangle.right - 20;
DrawThemeBackground(theme, dc, CP_DROPDOWNBUTTONRIGHT, CBXSR_NORMAL, &rectangle, nullptr);
But the above draws the arrow centered within the rectangle on a combobox background including the border, so I cannot use this without having a border within the combobox (which itself already has a border). I used theme-explorer to verify that the arrow is always on a background with borders.
In essence, my question is: How can I draw the background and the arrow at the appropriate position to emulate the look of a plain windows combobox?
What I have found out so far:
I can specify a clipping rectangle to clip away the aforementioned borders. But this poses the question of determining the exact position rectangle and the clipping rectangle: It seems that I can use GetThemeMargins to determine the margins, but that does not tell me how large the arrow is as a whole.
GetThemeBitmap might be useful in determining the exact size of the arrow, but as I read here and confirmed on my machine, using it with TMT_GLYPHDIBDATA does not work as advertised, and I would like to go without any workarounds, if possible.

How to resize between 3.5" and 4" screens (dynamic constraints in autolayout?)

I have one view filling the screen with a background image. Other views (text fields) are in exact positions (the background image includes the text field background images). When I change from 3.5" screen to 4", the text fields don't change in the same way that the background resizes. The bg image simply resizes to fill the screen, but the text fields jump out of alignment.
Is there a way to have two sets of constraints, one for each screen size? or is there a way to have views resize proportionally to another view?
EDIT:
Is there a way to have two sets of constraints, one for each screen
size?
Yes, by adding constraints programatically and checking [[UIScreen mainScreen] bounds] to get the screen size.
or is there a way to have views resize proportionally to another view?
Yes, you could set this up in interface builder. But it will be hard to manage, I would manage the constraints manually in code since you are using a custom background image the textviews need to position exactly
You're going to struggle to get these things to line up properly with the text view backgrounds being part of the background image.
You should amend your image assets and use the background property of UITextField to have an actual background image, and remove the boxes from your main background image. The icons could be separate images as well.
Failing that, it would make more sense to have the image stretch underneath the text boxes rather than on top.
Your layout is doing what it should do based on your description, but the image isn't stretching in the right way. In your screenshots, username is always the same distance from the top, and the others are the same distance from the bottom, but that isn't how image stretching works. I don't know how you've set it up but it would make sense to have a single image the size of the 4 inch screen, which has the bottom cut off for 3.5 inch devices, and constrain everything from the top.

Aligning text boxes

I'm have some data output text boxes (text boxes with no border and with the same background as the rest of the window) that I'm trying to align with a standard edit control + spin button, to represent a column of numbers, one of which can be edited:
I can manually align these in the Delphi / C++Builder form designer, but when I then view the form on a different version of Windows or at a different DPI, the text is no longer right-justified, presumably because of differences in the spin button spacing, borders, etc.
I can use EM_GETMARGINS to determine the width of the spin button, but how can I determine the size of the edit control's margins and borders? I've tried various combinations of EM_POSFROMCHAR, ClientToScreen, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CXEDGE), and GetThemeMargins, but so far, I can't find a combination that works and makes sense.
More details:
Environment is Delphi / C++Builder XE2.
The data output controls are TEdits with BorderStyle bsNone.
The edit + spin button is a TJvSpinEdit. From viewing its source, it uses EM_SETMARGINS to allow space for its spin button.
Use the Win32 API GetWindowRect() and GetClientRect() methods. The bordering will be the difference between the two rectangles. That will only give you the bordering, though. There could be extra spacing inside the client area.

font size bug with CGContextShowTextAtPoint

I have some rather simple code drawing some text into a CGContext. Here is an excerpt (slightly edited).
CGContextSelectFont(context, "Helvetica", 1.5, kCGEncodingMacRoman);
CGContextShowTextAtPoint(context, xpos, ypos, "Hello", 5);
The text renders ok. For some unknown reason, however, the font changes to a smaller size after I click in the view containing the context. Also when I resize the window containing the view the font returns to original size. What is the reason for this?
1.5 points is mighty tiny to begin with. Assuming no other scaling is in effect, that will be one whole pixel and a blurry pixel above it on the screen.
You're probably seeing a bug that I ran into myself: On entry into drawRect:, the current context's text matrix was not the identity matrix. In my case, I saw it contain a scale by 13 on both axes, plus a translation. (Possibly left over from drawing the title bar.) I filed this in Radar as #10585106, in case you want to file your own and cite it.
The solution is to set the text matrix back to the identity transform before trying to draw text.
Once you do that, you'll find that your text will be exactly as tiny as you asked for it to be. You should change your font size to something more reasonable; Core Text contains a function to get the system fonts (from which you can get their sizes), and AppKit's NSFont class contains methods for the same purpose.

Add shadow (recessed text effect) to Cocoa label without degrading text rendering quality

I'd like to create statusbar with text effect like in Safari or iTunes, i.e. recessed text.
However, if I simply add shadow in Interface Builder using Core Animation panel, OS X's worst text rendering kicks in:
What's the trick to get recessed text on a label and keep proper subpixel rendering?
There is a built-in way to do this:
[[yourTextField cell] setBackgroundStyle:NSBackgroundStyleRaised];
It's a cheap old trick: You draw the text in white at an offset and then draw the black text on top of it.
There is a hook for shadows in the text-drawing system, NSAttributedString's NSShadowAttributeName. But testing this out, it appears to kill the subpixel antialiasing as well.

Resources