0

Hi I'm trying to know the required width value for a text to fit a RECT.

So for now I'm trying to get the RECT dimensions according to a LPCWSTR, using the DT_CALCRECT format of DrawText().

Microsoft states that DT_CALCRECT

Determines the width and height of the rectangle. [...] DrawText returns the height of the formatted text[...]

The following code

LPCWSTR textCheck = L"12345";
RECT rectCheck = { 0, 0, 0, 0 };
int check = DrawText(
    hdc,
    textCheck,
    -1,
    &rectCheck,
    DT_CALCRECT);

returns the same value (16), textCheck being "12345" and "123456789".

Is it able to return only the height or I'm missing something?

Is DT_CALCRECT able to determines the width for itself but can't return it?

I expected DT_CALCRECT able to return the width and the height.

Raphael
  • 23
  • 3
  • I'm thinking about looking if `DrawText()` can draw vertically lol! – Raphael Jul 01 '23 at 06:22
  • Please [edit] your question to add additional information. – πάντα ῥεῖ Jul 01 '23 at 06:25
  • @πάνταῥεῖ I don't see what other relevant information I could add to the question, if you do please tell. – Raphael Jul 01 '23 at 06:28
  • So your 1st comment wasn't meant as additional information? – πάντα ῥεῖ Jul 01 '23 at 06:31
  • Just read the documentation again, it is pretty clear. Pay attention to `[in, out] LPRECT lprc,` and the comment on the return value (you don't use DT_VCENTER or DT_BOTTOM so it should be 0 all the time). So after you call the function `lprc` should contain the rectangle – Pepijn Kramer Jul 01 '23 at 06:35
  • I assume you know what an in/out parameter is? – Pepijn Kramer Jul 01 '23 at 06:36
  • The value "16" that it returns... is that the width or the height? I assume you're saying that it always returns the same width and the same height, even though the length of the string increases (and thus you would expect a larger width to be returned)? This functionality *does* work; I've used it many times. DrawText *can* draw text vertically, but you need to create a font with the escapement set to 900. – Cody Gray - on strike Jul 01 '23 at 06:40
  • @πάνταῥεῖ I meant I could try to draw the text vertically to get the width using the height but I guess that is not serious... ^^ – Raphael Jul 01 '23 at 06:45
  • @PepijnKramer I saw these `[in]` / `[in, out]` written in the documentations few times but it seems I ignored it. I'm now trying to learn how to use this to get the "returned" rectangle as you said. – Raphael Jul 01 '23 at 06:46
  • @CodyGray-onstrike I think the value "16" that it returns is the height, I am trying to get the width too. Thank you very much for the info about the font escapement! – Raphael Jul 01 '23 at 06:49
  • Details matter ;) Also try some of the flag combinations so you get more of a feel of what the documentation is trying to tell you – Pepijn Kramer Jul 01 '23 at 06:49
  • 1
    This is all covered in the [documentation](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawtextw) for the DrawText function. *If the function succeeds, the return value is the height of the text in logical units*. `DT_CALCRECT` is similarly described in detail. Stack Overflow should not be your first port of call when something doesn't work - always start by reading the API documentation. – Jonathan Potter Jul 01 '23 at 07:18
  • @JonathanPotter I agree I don't read enough the documentations. But I try a lot imo before posting on Stack Overflow (I search on Google and ask chatgpt). I think I use Stack Overflow when I'm stuck. – Raphael Jul 01 '23 at 18:36

1 Answers1

2

Unless I'm misunderstanding something, if you just want the width needed to render a string (on a single line), combo DT_CALCRECT with DT_SINGLELINE and then inspect the rectCheck which is an out param.

LPCWSTR textCheck = L"12345";
RECT rectCheck = { 0, 0, 0, 0 };
int check = DrawText(
    hdc,
    textCheck ,
    -1,
    &rectCheck ,
    DT_CALCRECT|DT_SINGLELINE);

int requiredWidth = rectCheck.right-rechCheck.left;

selbie
  • 100,020
  • 15
  • 103
  • 173
  • It works great, thank you so much! – Raphael Jul 01 '23 at 06:57
  • I would have used [GetTextExtentPoint32](https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-gettextextentpoint32w) instead: "*The GetTextExtentPoint32 function computes the width and height of the specified string of text.*" – Remy Lebeau Jul 01 '23 at 16:55
  • @RemyLebeau I've read a comment [here](https://stackoverflow.com/a/1126753/22157294) saying that using `DrawText()` "is a much better solution than `GetTextExtentPoint32` since it takes the mapping mode out of equation.", what do you think about it? – Raphael Jul 01 '23 at 18:39
  • I am starting to use `GetTextExtentPoint32` because the width of `DT_CALCRECT` was not the same when building as x86 and as x64. – Raphael Jul 02 '23 at 01:35
  • @Raphael - I'd love to see a [MCVE] of that. Are you sure the difference isn't from some change in dpi awareness between processes? – selbie Jul 02 '23 at 07:02
  • @selbie Can you suggest me a way to show you this minimal reproducible example? I don't know how to send it to you. I don't know about the dpi awarness but I think I tried `SetProcessDPIAware` before switching to `GetTextExtentPoint32`. – Raphael Jul 02 '23 at 09:59
  • @selbie I can't reproduce the difference anymore, I guess I thought it returned a difference because when building as x86, the child window background expanded to the parent's right bound, but when building as x64, the background just took the text width. I tested multiple times and just changing the architecture made this background width difference, but my code was a mess, it didn't even behave the same each Run without changing architecture. If I figure out what was causing this I will send you a comment. Sorry. – Raphael Jul 02 '23 at 21:59