Opened 15 months ago
Last modified 15 months ago
#18531 confirmed defect
wxStaticText doesn't work for very long text
Reported by: | followait | Owned by: | |
---|---|---|---|
Priority: | low | Milestone: | |
Component: | wxMSW | Version: | dev-latest |
Keywords: | msw10 | Cc: | followait@… |
Blocked By: | Blocking: | ||
Patch: | no |
Description
wxStaticText * pST = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER); std::ostringstream oss; int rows = 100; int cols = 100; for (int row = 0; row < rows; ++row) { for (int col = 0; col < cols; ++col) oss << "Test_" << col << '_' << row << ' '; oss << '\n'; } pST->SetLabel(oss.str());
In this case nothing displayed in wxStaticText.
If set rows to 10 and cols to 10, it works properly.
Change History (11)
comment:1 Changed 15 months ago by pb101
- Cc pbfordev@… added
- Status changed from new to confirmed
comment:2 follow-up: ↓ 3 Changed 15 months ago by pb101
- Cc pbfordev@… removed
Oops, sorry in the Win32 example | SS_GRAYRECT was added accidentally and must be removed from the following line
hStaticText = CreateWindow(_T("STATIC"), _T(""), WS_CHILD | WS_VISIBLE | SS_LEFT | SS_GRAYRECT,
otherwise the control would never show any text at all.
comment:3 in reply to: ↑ 2 Changed 15 months ago by vadz
- Priority changed from normal to low
- Summary changed from wxStaticText not work for large text to wxStaticText doesn't work for very long text
Thanks for testing this, especially at Win32 level, as this shows that it's "not our problem". Of course, it doesn't mean that it isn't a problem, but, realistically, I don't see what could be done about it. Moreover, it's simple to work around it in the application code by using wxGenericStaticText -- but this can't be easily done inside the library, unfortunately, as wxStaticText really wants to be the native control. So in practice it seems very unlikely that anything will be ever done at all about it.
Replying to pb101:
Oops, sorry in the Win32 example | SS_GRAYRECT was added accidentally and must be removed from the following line
hStaticText = CreateWindow(_T("STATIC"), _T(""), WS_CHILD | WS_VISIBLE | SS_LEFT | SS_GRAYRECT,otherwise the control would never show any text at all.
I took the liberty of editing your reply (apparently only I have the permissions to do it?) to remove this style.
comment:4 Changed 15 months ago by pb101
- Cc pbfordev@… added
- Keywords msw10 added
I tried running the very same wxWidgets and Win32 executables that did not show any text on Windows 10 also in Virtual Box Windows 7 machine. Both showed the text there, so somehow this seems to be Windows 10 related.
Setting compatibility to older Windows versions when running on Windows 10 did not help.
BTW, I actually can edit my posts but I did not notice it before. Thanks for the tip!
comment:5 Changed 15 months ago by awi
Isn't the root cause (string longer than 32767 pixels) the same as for #17379?
comment:6 Changed 15 months ago by vadz
awi, you're probably right, thanks for the reminder. Pretty weird that it works under MSW 7 though, the other bug is reproducible there too.
Anyhow, I guess we could check the text extent and truncate it automatically to fit in 2^15 pixels to display at least something in this case, which would be better than the current behaviour. OTOH using wxGenericStaticText (assuming it works) would still be a better workaround.
comment:7 Changed 15 months ago by followait
- Cc followait@… added
Windows is hard, but SetWindowText should return FALSE in the case, but it doesn't.
So no sense to check the return value of SetWindowText inside 'wxStaticText::SetLabel`.
wxStaticText::SetLabel can check the length of text before calling SetWindowText.
What about add a return value for wxStaticText::SetLabel?
comment:8 Changed 15 months ago by vadz
Realistically, nobody is going to check the return value of SetLabel(), so this doesn't seem very useful.
comment:9 Changed 15 months ago by followait
- Cc followait@… removed
Some geek will check every return value that may fail, maybe during their early years.
I think explicity (i.e. a return value here) is always good, reason:
With a return value:
- The new serious programmer can simply check the return value theoretically, and no need for practical considerrations.
- The practical programmers can ignore the return value explicitly, and they can see they are ignoring the return value explicitly.
Without a return value, wx ignores the return value implicitly, but mislead the programmer to think that the function never fails.
I think with less policy wx will be more concise and more flexible.
comment:10 follow-up: ↓ 11 Changed 15 months ago by pb101
- Cc pbfordev@… removed
Firstly, I too find hard to believe that people would start checking the return value of wxControl::SetLabel(). However, I do believe that programmers diligent enough to do that would not use wxStaticText for displaying texts that can have (tens) of thousands of characters: they would use a read-only multi-line wxTextCtrl (with wxTE_RICH2), which is much better suited for such task.
Secondly, using string length alone is not good enough to tell if the text will be displayed or not. It seems that Win7 (VM in a VirtualBox) can handle a quite longer string than Win10, so there is more to it (see the referenced ticket). I.e, one cannot accurately tell beforehand whether the text will be displayed or not.
Thirdly, I found out that when the text is too long and nothing is displayed, ::SetWindowText() still returns TRUE but ::GetWindowTextLength() seems to return 0 instead of the length of the string passed to ::SetWindowText(). However, wxControl stores the label internally and returns it from wxControl::GetLabel(), so the wxWidgets programmer cannot use this.
comment:11 in reply to: ↑ 10 Changed 15 months ago by followait
- Cc followait@… added
Replying to pb101:
Firstly, I too find hard to believe that people would start checking the return value of wxControl::SetLabel(). However, I do believe that programmers diligent enough to do that would not use wxStaticText for displaying texts that can have (tens) of thousands of characters: they would use a read-only multi-line wxTextCtrl (with wxTE_RICH2), which is much better suited for such task.
It's policy, a lib may leave the policy to users.
Secondly, using string length alone is not good enough to tell if the text will be displayed or not. It seems that Win7 (VM in a VirtualBox) can handle a quite longer string than Win10, so there is more to it (see the referenced ticket). I.e, one cannot accurately tell beforehand whether the text will be displayed or not.
Thirdly, I found out that when the text is too long and nothing is displayed, ::SetWindowText() still returns TRUE but ::GetWindowTextLength() seems to return 0 instead of the length of the string passed to ::SetWindowText(). However, wxControl stores the label internally and returns it from wxControl::GetLabel(), so the wxWidgets programmer cannot use this.
It's about implentation.
For Windows, some work arounds:
- hard code text limit for each version of OS
- simply use the lowest valid length.
For wx, source code there. Because wxControl stores window text commonly, checking validity before SetLabel seems the best solution.
Thanks for your digging.
I can confirm this.
But it seems that the native Windows control behaves the same way. SetWindowText() returns TRUE even for the too long text. The control should not have any real-world limit for text length.
In wxWidgets, the issue can be easily fixed by using any of the wxST_ELLIPSIZE_* flags.
SSCCE for wxWidgets and Win32 to reproduce the issue follows.
wxWidgets
Win32