libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
9.94k stars 1.84k forks source link

SDL_ShowSimpleMessageBox cuts off last character of message when its longer than 3 character #1380

Closed SDLBugzilla closed 8 months ago

SDLBugzilla commented 3 years ago

This bug report was migrated from our old Bugzilla tracker.

These attachments are available in the static archive:

Reported in version: 2.0.1 Reported for operating system, platform: Windows (All), All

Comments on the original bug report:

On 2014-03-02 22:34:45 +0000, Coriiander wrote:

When I was just checking out SDL_ShowSimpleMessageBox (just to see how it looked like, I don't need it myself), I noticed a bug. When a message that is longer than 3 characters, the displayed message is incorrect. It cuts off the last character. It 'works fine' for messages upto and including 3 characters in length. I'm building this with Microsoft Visual Studio 2008, with in the build options Character Set = 'Not Set'.

Code to reproduce this bug:

include "SDL.h"

int main(int argc, char* argv[]) { SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Title", "abc", NULL); return 0; }

Here's the various output messages for various input messages: a: a ab: ab abc: abc abcd: abc abcde: abcd abcdef: abcde abcdefg: abcdef abc..xyz: abc..xy

I have not dived into SDL's source code to find out where the problem is, though I can imagine it may have something to do with a bug related to null-terminator char while converting the string format.

On 2015-02-19 05:22:17 +0000, Ryan C. Gordon wrote:

Marking a large number of bugs with the "triage-2.0.4" keyword at once. Sorry if you got a lot of email from this. This is to help me sort through some bugs in regards to a 2.0.4 release. We may or may not fix this bug for 2.0.4, though!

On 2015-04-07 04:57:54 +0000, Ryan C. Gordon wrote:

(sorry if you get a lot of copies of this email, I'm marking several bugs at once)

Marking bugs for the (mostly) final 2.0.4 TODO list. This means we're hoping to resolve this bug before 2.0.4 ships if possible. In a perfect world, the open bug count with the target-2.0.4 keyword is zero when we ship.

(Note that closing a bug report as WONTFIX, INVALID or WORKSFORME might still happen.)

--ryan.

On 2015-05-01 16:21:11 +0000, igor wrote:

Also it would be nice to have this function implemented for Android.

On 2015-05-02 00:53:55 +0000, Alex Szpakowski wrote:

(In reply to igor from comment # 3)

Also it would be nice to have this function implemented for Android.

It is implemented for SDL 2.0.4: https://hg.libsdl.org/SDL/rev/6cd8e6b54f4d

On 2015-05-02 10:09:28 +0000, igor wrote:

It's awesome, need to get hg version...

On 2015-05-28 19:15:29 +0000, Sam Lantinga wrote:

I'm not able to reproduce this. Are you still seeing this problem with the latest SDL build? http://www.libsdl.org/tmp/SDL-2.0.zip

If so, can you set a breakpoint in WIN_ShowMessageBox() and see what's happening?

Do you have display scaling turned on?

On 2015-05-28 21:02:42 +0000, igor wrote:

I'm not a reporter but had issue some time ago too, I was getting last word cut off. Try to use message from e.g 9 words in one line.

On 2015-05-28 21:10:52 +0000, igor wrote:

Try this one.

SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "FLARE: Default mod not found", "Default mod should be installed to proceed. Game will exit.", NULL);

If it works, then I will need to double-check it, not sure if above linecwas failing...

On 2015-05-29 02:21:27 +0000, Coriiander wrote:

I did the original report. I cannot check right now, though I will be able tomorrow. I'll report back once tested.

On 2015-05-29 11:30:47 +0000, igor wrote:

Created attachment 2167 Image of truncated text

On 2015-05-29 11:31:43 +0000, igor wrote:

Windows 7 x64 Mingw32 build of application and of provided sdl snapshot http://www.libsdl.org/tmp/SDL-2.0.zip

Call: SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "FLARE", "ERROR: No \"default\" mod found.", NULL);

Image attached.

On 2015-05-29 14:50:09 +0000, igor wrote:

Not providing nCount (string size) to DrawText(FontDC, wmessage, -1, &TextSize, DT_CALCRECT); causes issue. If -1 is replaced with positive number, all is ok. So DrawText doesn't calculate wmessage size correctly.

On 2015-05-29 15:00:02 +0000, igor wrote:

wcslen(wmessage) reports 30... So maybe it's something with last two parameters...

On 2015-05-29 15:34:53 +0000, igor wrote:

Replacing DT_CALCRECT with e.g. DT_BOTTOM and setting TextSize manually fixes issue. There are some threads in internet about TextSize is not calculated correctly when using DT_CALCRECT, but no idea how to calculate it correctly.

On 2015-06-02 12:01:12 +0000, igor wrote:

I propose to split input text into lines manually, and calculate each char width, then sum each char widths. DT_CALCRECT doesn't provide correct result, and we don't use any other flags(like text wrapping), so manual calculation should be ok.

On 2015-06-03 07:57:08 +0000, igor wrote:

When looking here: https://msdn.microsoft.com/en-us/library/dd144938(VS.85).aspx you can see that: "Because some devices kern characters, the sum of the extents of the characters in a string may not be equal to the extent of the string."

When calculating text width with next code:

int widthInUnits = 0; for (int i = 0; i < wcslen(wmessage); i++) { SIZE size; size.cx = 0; size.cy = 0; GetTextExtentPoint32(hdc, wmessage + i, 1, &size); widthInUnits += size.cx; }

I get the same result as DrawText(...DT_CALCRECT). So I guess both GetTextExtentPoint32() and DrawText(...DT_CALCRECT) do the same work. And in both cases we ignore kerning. A fast hack would be just add one pixel to each symbol (I guess doesn't matter what of two approaches we use - whole text width calculation, or sum of all character widths). The hard fix will be to take kerning into account somehow, but no idea how to do this...

On 2015-06-03 07:59:22 +0000, igor wrote:

GetTextExtentPoint32(hdc, wmessage, wcslen(wmessage), &size) gives the same result, so it really ignores kerning in all cases

On 2015-06-03 08:08:35 +0000, igor wrote:

Well, not sure how to call it, kerning or spacing, but sum of character widths is the same as text width in our case, so in case of spaces between characters, calculated width will be smaller then real text width, so text will not fit.

On 2015-06-05 10:59:47 +0000, igor wrote:

I got more info. I have "medium font size 125%" set in Windows 7 Display preferences, if I change it to smallest (100%), text fits nicely. So this is definitely issue with winAPI. Can we do something with this?

On 2015-06-05 16:38:06 +0000, Coriiander wrote:

First of all sorry for my late reply. I wasn't at home and didn't have the time for looking into it. Here's my reply. It's lenghty, and I already say: it's a relatively complicated thing for such a small feature.

The bug is related to the Windows text/display scaling. Like you mentioned at, for example, 125% text scaling. One might think only the visually impaired use this feature, but that's far from the case; it's an often used thing. I use it myself as well (150% even), hence I ran into the bug I suppose.

But yes, there is things that can be done. Taking a look at the .NET-framework controls/forms, you'll see they use an AutoScale-property. This property can be set to things like Font and DPI. The rendering framework will then take care of appropriate scaling, taking the system-defined scaling into account. The system-defined scaling value can be obtained in two ways.

Method 1: desktopDc = GetDC(NULL); horizontalDPI = GetDeviceCaps(desktopDc,LOGPIXELSX); verticalDPI = GetDeviceCaps(desktopDc,LOGPIXELSY);

Method2: Windows Registry (Win32): HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics/AppliedDPI Windows Registry (WinRT): HKEY_CURRENT_USERControlPanel\Desktop\LogPixels

The values can be: 96 = 100% scaling on every display 120 = 125% scaling on every display 144 = 150% scaling on every display 192 = 200% scaling on every display

= *100/96 scaling on every display These numbers can be used to calculate the approriate dialog size. As a matter of fact, these values *SHOULD* also be used for Window creation in fullscreen mode! I don't know if there are currently issues with this, but I can remember a while ago there was an (unreported) bug when toggling from fullscreen back to windowed on scaled systems. Now the difficulty is there in that it might actually differ from display to display. This has to do with the amount of scanlines or vertical resolution on the various displays. By using Method1 (GetDeviceCaps) we should query the desired display where the dialog is to be displayed. We query its vertical resolution and its LogPixelsX/Y. For further information, see this article at TechNet: https://technet.microsoft.com/en-us/library/dn528846.aspx#scalingmode Cheers

On 2015-06-05 17:31:52 +0000, Coriiander wrote:

To add to my previous comment:

Forget about the registry values. Older versions of Windows have a system-wide key, while newer version have a user-specific key as well. It's best to just use the API (GetDeviceCaps). For WinRT other quite useful APIs have been introduced. See https://msdn.microsoft.com/en-us/library/windows/desktop/dn469266%28v=vs.85%29.aspx for more in-depth information for both Win32 and WinRT.

Also a suggestion: Seeing that display querying is already built-in to SDL, it might be a good idea to store scaling with the display info. These scaling values can be used by entire SDL, so also for things like toggling fullscreen, acquiring and calculating correct window-position/size, etc. I figure this should be especially important on touch-enabled devices.

On 2015-06-05 17:38:37 +0000, Alex Szpakowski wrote:

How does that interact with the SetProcessDpiAwareness / SetProcessDpiAware functions (which SDL doesn't use at all yet), and the SDL_WINDOW_ALLOW_HIGHDPI flag (which also isn't used in Windows yet)?

e.g. https://msdn.microsoft.com/en-ca/magazine/dn574798.aspx &

On 2015-06-05 18:19:40 +0000, Coriiander wrote:

I don't know. I have no experience with the WinRT API myself. I believe David Ludwig has done work on SDL with regards to WinRT; perhaps he knows. SetProcessDpiAware isn't available on older Windows-versions so I don't think that's the road to take.

On 2015-06-05 18:23:48 +0000, Alex Szpakowski wrote:

They are for Windows desktop apps. SetProcessDpiAware was added in Windows Vista to allow for high-DPI / retina support in programs (i.e. DPI scaling awareness.) SetProcessDpiAwareness was added in Windows 8.1 and allows programs to account for per-monitor DPI scaling differences.

On 2015-06-05 18:27:36 +0000, Alex Szpakowski wrote:

Here's some more info: https://msdn.microsoft.com/en-us/library/windows/desktop/dd464659(v=vs.85).aspx

If a program reports itself as DPI-aware, then Windows no longer does automatic scaling for it. This is important for games, since the framebuffer resolution will be a lot higher (and performance will be drastically affected) when this happens in high-DPI situations – that's why it's an opt-in feature in windows, OS X, and in SDL's own API.

On 2015-06-08 02:37:59 +0000, Sam Lantinga wrote:

Created attachment 2173 Windows 8.1, text not truncated

Maybe this is specific to Windows 7? I just tried on Windows 8.1 and there was no issue here.

Out of curiosity, is your game DPI aware?

On 2015-06-08 03:17:23 +0000, Coriiander wrote:

I don't know about Windows versions post 7. The report was filed as an issue on Windows 7. Note that the OS's display/text scaling is enabled; it's set to 150%. This is mostlikely cause of the problem. The project I was using this in (merely for testing purposes) was not DPI-aware.

On 2015-06-08 03:21:04 +0000, Coriiander wrote:

Like issues with text scaling, there's also other issues with regards to window metrics when text/desktop scaling is enabled (e.g. metric values, toggling back and forth between windowed and fullscreen). It seems the 'bug' resides on a deeper level as SDL doesn't really take the system's DPI scaling into account. As suggested in a prior reply this might be worthwhile to look into. It shouldn't be too difficult as display information retrieval is already implemented within SDL anyway.

On 2015-06-08 08:01:32 +0000, igor wrote:

I have tried on Windows 8. No issue on 100% text scaling, but issue present on 125% text scaling. Sam, are you sure you have changed text scaling?

On 2015-06-08 08:04:31 +0000, igor wrote:

Note that my test application doesn;t have any WinAPI calls, only cross-platform code, so I guess my app doesn't have any DPI related non-default settings.

On 2015-07-18 19:59:58 +0000, Coriiander wrote:

I recently had to add a custom manifest to one of my Visual C projects (somehow never had to do it before). This led me to how users should request DPI-awareness by embedding a dpiAware-entry in the application manifest (note: application, not shared library).

true

And 'lo, behold - correct metrics!

As MSDN states @ https://msdn.microsoft.com/en-us/library/windows/desktop/ms633543(v=vs.85).aspx

DLLs should accept the dpi setting of the host process rather than call SetProcessDPIAware themselves. To be set properly, dpiAware should be specified as part of the application (.exe) manifest. (dpiAware defined in an embedded DLL manifest has no affect.) The following markup shows how to set dpiAware as part of an application (.exe) manifest.

On 2015-12-28 19:24:45 +0000, Ryan C. Gordon wrote:

Ok, just following up here: was the consensus that apps should set a value in their manifests, and there's nothing SDL needs to (or even should) do here?

Trying to decide if I should close this bug or fix something.

--ryan.

On 2016-01-04 09:17:55 +0000, igor wrote:

I was unable to fix issue with manifest file under Windows 7 with VS... Can you guys re-check it?

slouken commented 1 year ago

SDL 2.0 is now in maintenance mode, and all inactive issues are being closed. If this issue is impacting you, please feel free to reopen it with additional information.