Problem printing text with wxWidgets 3.2.2.1

123 views
Skip to first unread message

Fulvio Senore

unread,
Sep 4, 2023, 2:07:09 PM9/4/23
to wxWidgets Users
I have recently upgraded a large program from wxWindgets 3.1.1 to 3.2.2.1.

As usual I had a couple of problems caused by unexpected changes, but I
was able ti fix them.

I still have another problem and I really don't know how to fix it.

The program needs to print text. This is a wxWidgets area that is not
clear to me, but many years ago I was able to write some code that was
able to print, for example, a 10 points font at 10 points size so I was
happy.

After the upgrade to 3.2.2.1, under Windows (I don't know for other
platforms), if the screen text size is set to more that 100%, the
program prints text smaller than the right size. The size reduction the
inverse of the selected screen text increase.
If I create a pdf with wxPdfDocument::wxPdfDC the text is still printed
at the correct size.

It looks like the wxDC draws the text smaller than in previous versions,
but it seems that it is not a matter of global scale: if I print a form
made by many small boxes with text inside them, the boxes are still
drawn at the correct size and text is drawn at the correct position.
Simply the text inside the boxed is smaller.

Does anybody have a suggestion to fix this problem?

Thanks in advance.

Fulvio Senore

Vadim Zeitlin

unread,
Sep 5, 2023, 4:56:00 PM9/5/23
to wxWidgets Users
On Mon, 4 Sep 2023 20:06:58 +0200 Fulvio Senore wrote:

FS> As usual I had a couple of problems caused by unexpected changes, but I
FS> was able ti fix them.

If you see anything not mentioned in the change log, please report it.

FS> After the upgrade to 3.2.2.1, under Windows (I don't know for other
FS> platforms), if the screen text size is set to more that 100%,

Do you mean the screen DPI or the separate text magnification option?

FS> the program prints text smaller than the right size.

Is this reproducible in the printing sample? If yes, please open an issue
for it as this is supposed to work. If not, you really need to show us what
is your code doing [differently from the sample] or, realistically, provide
a small patch to the sample reproducing the problem.

Regards,
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
https://www.tt-solutions.com/

Fulvio Senore

unread,
Sep 6, 2023, 12:47:55 PM9/6/23
to wx-users

Il 05/09/2023 22:55, Vadim Zeitlin ha scritto:
> On Mon, 4 Sep 2023 20:06:58 +0200 Fulvio Senore wrote:
>
> FS> As usual I had a couple of problems caused by unexpected changes, but I
> FS> was able ti fix them.
>
> If you see anything not mentioned in the change log, please report it.


All these problems have been found or reported under Windows.

1) zlib symbols are now prefixed by default so using them leads to
linker errors.

2) wxBitmapButton: if screen magnification is set to 200% the button
becomes twice as wide and tall. If magnification is lower then 200% the
button maintains the original size.
This screwed up the layout of a window for user with such an enlargement.

3) The color of the lines among wxGrid cells has become much lighter. I
can understand why: now it is the same color as the color used in the
header, but it is really very light and with high dpi screens it becomes
almost invisible.

>
> FS> After the upgrade to 3.2.2.1, under Windows (I don't know for other
> FS> platforms), if the screen text size is set to more that 100%,
>
> Do you mean the screen DPI or the separate text magnification option?


The screen magnification option: right click the desktop, then select
"screen settings" or something similar (my Windows copy is in Italian).

>
> FS> the program prints text smaller than the right size.
>
> Is this reproducible in the printing sample? If yes, please open an issue
> for it as this is supposed to work. If not, you really need to show us what
> is your code doing [differently from the sample] or, realistically, provide
> a small patch to the sample reproducing the problem.
>


It took me some time but I was able to solve the problem.

In the printout, when doing scale computations, the sample uses

GetPPIScreen(&ppiScreenX, &ppiScreenY);

while I used

wxScreenDC sdc;
ppiScreenX = sdc.GetPPI().GetWidth();
ppiScreenY = sdc.GetPPI().GetHeight();

For some reason my code returned a higher PPI value when magnification
is on, leading to smaller text. In wxWidgets 3.1.3 the code worked
correctly.

As I discovered this problem I started to remember that I already had
problems with this code. I digged in the repository and in december 2019
I changed the code from the sample single line to the current 3 lines
because in wxWidgets 3.1.3 I had problems with test size.
It looks like the current code was a workaround for some 3.1.3 problem
and now I have to revert to the original code.

I still would like to know why wxPrintout::GetPPIScreen() and
wxScreenDC::GetPPI() return different values.

In my Windows computer now wxPrintout::GetPPIScreen() always return 96.
wxScreenDC::GetPPI() return 96 with 100% magnification and
proportionally larger values as magnification increases.

Fulvio

Vadim Zeitlin

unread,
Sep 6, 2023, 4:01:39 PM9/6/23
to wx-u...@googlegroups.com
On Wed, 6 Sep 2023 18:47:48 +0200 Fulvio Senore wrote:

FS> > FS> After the upgrade to 3.2.2.1, under Windows (I don't know for other
FS> > FS> platforms), if the screen text size is set to more that 100%,
FS> >
FS> > Do you mean the screen DPI or the separate text magnification option?
FS>
FS> The screen magnification option: right click the desktop, then select
FS> "screen settings" or something similar (my Windows copy is in Italian).

It's called "Display settings" in English, but I just wanted to make sure
we were speaking of "Change the size of text, apps and other items"
combobox there, with the values ranging from 100% to 350% in it because I
believe there is some other setting in Windows 11 which scales the text
only.

FS> It took me some time but I was able to solve the problem.
FS>
FS> In the printout, when doing scale computations, the sample uses
FS>
FS> GetPPIScreen(&ppiScreenX, &ppiScreenY);
FS>
FS> while I used
FS>
FS> wxScreenDC sdc;
FS> ppiScreenX = sdc.GetPPI().GetWidth();
FS> ppiScreenY = sdc.GetPPI().GetHeight();
FS>
FS> For some reason my code returned a higher PPI value when magnification
FS> is on, leading to smaller text.

Well, if you use higher DPI for your screen, it's expected that wxScreenDC
returns a higher value, so I don't see any problem here.

FS> I still would like to know why wxPrintout::GetPPIScreen() and
FS> wxScreenDC::GetPPI() return different values.
FS>
FS> In my Windows computer now wxPrintout::GetPPIScreen() always return 96.

This was changed in 1a1d19e93b (Improve print preview and printing with
high DPI, 2022-04-20) which was part of 3.1.7 and it looks like it
compensated for the problems previously introduced into this code when
adding high DPI support.

I'm not sure if returning the standard DPI, as wxPrintout::GetPPIScreen()
does by default, is the right thing to do, but it looks like all its code
assumes that this is the case and we'd need to change a lot of things if we
changed this. To be honest, it's not clear at all why should wxPrintout
care about the screen DPI: after all, what's printed shouldn't depend on
whether you print it on a computer with a normal or high DPI monitor (and
what if you have both of them connected to the same computer, as I do right
now?). So I think that perhaps we should explain in the documentation that
wxPrintout "screen PPI" is not really screen PPI at all... And maybe we
should provide GetPrinterScaleFactor() or something like this to make it
unnecessary to use GetPPIScreen(), and GetPPIPrinter(), explicitly.

Fulvio Senore

unread,
Sep 7, 2023, 3:45:17 PM9/7/23
to wx-users


Il 06/09/2023 22:01, Vadim Zeitlin ha scritto:
> On Wed, 6 Sep 2023 18:47:48 +0200 Fulvio Senore wrote:
>

>
> FS> It took me some time but I was able to solve the problem.
> FS>
> FS> In the printout, when doing scale computations, the sample uses
> FS>
> FS> GetPPIScreen(&ppiScreenX, &ppiScreenY);
> FS>
> FS> while I used
> FS>
> FS> wxScreenDC sdc;
> FS> ppiScreenX = sdc.GetPPI().GetWidth();
> FS> ppiScreenY = sdc.GetPPI().GetHeight();
> FS>
> FS> For some reason my code returned a higher PPI value when magnification
> FS> is on, leading to smaller text.
>
> Well, if you use higher DPI for your screen, it's expected that wxScreenDC
> returns a higher value, so I don't see any problem here.

I agree. I just don't understand because wxPrintout::GetPPIScreen()
returns a different value.
>
> FS> I still would like to know why wxPrintout::GetPPIScreen() and
> FS> wxScreenDC::GetPPI() return different values.
> FS>
> FS> In my Windows computer now wxPrintout::GetPPIScreen() always return 96.
>
> This was changed in 1a1d19e93b (Improve print preview and printing with
> high DPI, 2022-04-20) which was part of 3.1.7 and it looks like it
> compensated for the problems previously introduced into this code when
> adding high DPI support.

You are probably right. Now I had to revert my code to the one used in
older versions, before 3.1.3.

>
> I'm not sure if returning the standard DPI, as wxPrintout::GetPPIScreen()
> does by default, is the right thing to do, but it looks like all its code
> assumes that this is the case and we'd need to change a lot of things if we
> changed this. To be honest, it's not clear at all why should wxPrintout
> care about the screen DPI: after all, what's printed shouldn't depend on
> whether you print it on a computer with a normal or high DPI monitor (and
> what if you have both of them connected to the same computer, as I do right
> now?). So I think that perhaps we should explain in the documentation that
> wxPrintout "screen PPI" is not really screen PPI at all... And maybe we
> should provide GetPrinterScaleFactor() or something like this to make it
> unnecessary to use GetPPIScreen(), and GetPPIPrinter(), explicitly.
>

I must confess that many years ago, when I tried to write code to print
text from wxWidgets, I read all the documentation and the sample source
code.
I did not understand anything so I simply copied some code from the
sample: it happened to work, and I was happy.

IMHO a feature that is very complicated and difficult to understand,
just to accomplish a basic task, has some design flaws.
It would be nice to just set the font size and print, like it happened
with the venerable Visual Basic long time ago.

Anyway, now I have my own code that works (usually) so I am satisfied.

Regards

Fulvio



Vadim Zeitlin

unread,
Sep 7, 2023, 5:04:00 PM9/7/23
to wx-u...@googlegroups.com
On Thu, 7 Sep 2023 21:45:05 +0200 Fulvio Senore wrote:

FS> I must confess that many years ago, when I tried to write code to print
FS> text from wxWidgets, I read all the documentation and the sample source
FS> code.
FS> I did not understand anything so I simply copied some code from the
FS> sample: it happened to work, and I was happy.
FS>
FS> IMHO a feature that is very complicated and difficult to understand,
FS> just to accomplish a basic task, has some design flaws.
FS> It would be nice to just set the font size and print, like it happened
FS> with the venerable Visual Basic long time ago.

I usually recommend people to use wxHtmlEasyPrinting if they can as it's,
indeed, much easier than dealing with wxPrintout and what not. But it can't
be used in all cases, of course, and I don't know how much the existing API
can be really simplified without losing some functionality, but it should
be possible to improve it at least somewhat.

As everything else in wxWidgets, it basically just waits until someone
becomes motivated enough to actually do it...

Fulvio Senore

unread,
Sep 12, 2023, 1:44:06 PM9/12/23
to wx-users
Sorry for the delay: I've been out of home for a few days.

Since I have already solved the printing problem I could write some code
to print in a simple way.

How should I discuss and design this code?

Fulvio

Vadim Zeitlin

unread,
Sep 12, 2023, 2:15:29 PM9/12/23
to wx-u...@googlegroups.com
On Tue, 12 Sep 2023 19:43:56 +0200 Fulvio Senore wrote:

FS> Since I have already solved the printing problem I could write some code
FS> to print in a simple way.
FS>
FS> How should I discuss and design this code?

Sorry, I don't know how exactly should it be designed. Maybe we can just
simplify the existing wxPrintout (if necessary, by deriving some
wxSimplePrintout from it). Maybe we could somehow do without wxPrintout at
all, e.g. by handling some new wxEVT_PRINT_PAGE etc.

At very high level, we need to identify the current pain points and try to
provide API avoiding them. This is not very helpful, of course, but I just
don't have enough time to write something that would be, sorry.

If you can come up with something, please do post the proposed new API and
let's discuss it.

Thanks in advance,

Fulvio Senore

unread,
Sep 13, 2023, 4:28:20 PM9/13/23
to wx-users


Il 12/09/2023 20:15, Vadim Zeitlin ha scritto:
> On Tue, 12 Sep 2023 19:43:56 +0200 Fulvio Senore wrote:
>
> FS> Since I have already solved the printing problem I could write some code
> FS> to print in a simple way.
> FS>
> FS> How should I discuss and design this code?
>
> Sorry, I don't know how exactly should it be designed. Maybe we can just
> simplify the existing wxPrintout (if necessary, by deriving some
> wxSimplePrintout from it). Maybe we could somehow do without wxPrintout at
> all, e.g. by handling some new wxEVT_PRINT_PAGE etc.
>
> At very high level, we need to identify the current pain points and try to
> provide API avoiding them. This is not very helpful, of course, but I just
> don't have enough time to write something that would be, sorry.
>
> If you can come up with something, please do post the proposed new API and
> let's discuss it.
>

I did not express myself well enough, sorry. When I asked "How should I
discuss and design this code?" I was thinking at the tools to use: this
mailing list, the wx-dev one or something else. I was also thinking at
the procedures to follow.

Anyway the base idea is the following.

Create a class to encapsulate a print job. Add methods to start the job,
write text and some graphics primitives, to start a new page and to end
the job starting the real printing process.

All method calls are stored in memory until the job is ended, then real
printing begins. A printout is created and all the commands are
retrieved from memory ed executed in the printout.

This ought to shield the user from the complexity of printing,
presenting a very simple interface.

Do you think that this is a reasonable approach?

Fulvio



Vadim Zeitlin

unread,
Sep 13, 2023, 4:41:57 PM9/13/23
to wx-u...@googlegroups.com
On Wed, 13 Sep 2023 22:28:08 +0200 Fulvio Senore wrote:

FS> I did not express myself well enough, sorry. When I asked "How should I
FS> discuss and design this code?" I was thinking at the tools to use: this
FS> mailing list, the wx-dev one or something else. I was also thinking at
FS> the procedures to follow.

Ah, sorry for misunderstanding you. The wx-dev list is probably the best
place for something like this.

FS> Create a class to encapsulate a print job. Add methods to start the job,
FS> write text and some graphics primitives, to start a new page and to end
FS> the job starting the real printing process.
FS>
FS> All method calls are stored in memory until the job is ended, then real
FS> printing begins. A printout is created and all the commands are
FS> retrieved from memory ed executed in the printout.
FS>
FS> This ought to shield the user from the complexity of printing,
FS> presenting a very simple interface.
FS>
FS> Do you think that this is a reasonable approach?

AFAICS this means reimplementing Windows metafiles in wxWidgets or, at
least, something very similar to it, and this is not easy to do at all and
all but impossible to do efficiently at our level.

I think we need to keep the idea of having some function called with wxDC
parameter and rendering onto it. But it could be a callback instead of a
virtual function, e.g. a std::function<void (int page, wxDC&)> or something
like this.

Regards,

Fulvio Senore

unread,
Sep 15, 2023, 4:19:17 AM9/15/23
to wx-users


Il 13/09/2023 22:41, Vadim Zeitlin ha scritto:
> FS> Create a class to encapsulate a print job. Add methods to start the job,
> FS> write text and some graphics primitives, to start a new page and to end
> FS> the job starting the real printing process.
> FS>
> FS> All method calls are stored in memory until the job is ended, then real
> FS> printing begins. A printout is created and all the commands are
> FS> retrieved from memory ed executed in the printout.
> FS>
> FS> This ought to shield the user from the complexity of printing,
> FS> presenting a very simple interface.
> FS>
> FS> Do you think that this is a reasonable approach?
>
> AFAICS this means reimplementing Windows metafiles in wxWidgets or, at
> least, something very similar to it, and this is not easy to do at all and
> all but impossible to do efficiently at our level.
>

I never used metafiles so don't understand your sentence. Isn't it
possible to store the metafile in memory and print it later, together
with the other commands?

Anyway, I was thinking of this class of a simple way to print simple
documents, mainly text-based. Just think of a report. In this case it
ought to be enough to support text, some simple graphic primitives and
images in a few standard formats.

If the purpose is to support everything then the task would be different.

> I think we need to keep the idea of having some function called with wxDC
> parameter and rendering onto it. But it could be a callback instead of a
> virtual function, e.g. a std::function<void (int page, wxDC&)> or something
> like this.
>

This is surely a good idea. We could also add a function to get the wxDC.

Fulvio

Vadim Zeitlin

unread,
Sep 15, 2023, 8:36:38 AM9/15/23
to wx-u...@googlegroups.com
On Fri, 15 Sep 2023 10:19:11 +0200 Fulvio Senore wrote:

FS> I never used metafiles so don't understand your sentence. Isn't it
FS> possible to store the metafile in memory and print it later, together
FS> with the other commands?

It is, metafile is exactly a sequence of graphics operations stored in
memory. But metafiles are MSW-only and don't support all graphics
operations.

FS> Anyway, I was thinking of this class of a simple way to print simple
FS> documents, mainly text-based. Just think of a report. In this case it
FS> ought to be enough to support text, some simple graphic primitives and
FS> images in a few standard formats.

Unfortunately I don't think you can define the boundaries of "simple".
Even the simplest reports may want to embed a logo, so now you also need to
allow printing bitmaps. And you need lines to draw around tables. And so
on.

FS> This is surely a good idea. We could also add a function to get the wxDC.

I do think we need to keep using wxDC, it's just everything else (i.e.
page setup mostly, I think) that it would be nice to simplify.

Fulvio Senore

unread,
Sep 18, 2023, 10:45:21 AM9/18/23
to wx-users
I had an idea to make things simpler to code and keep them reasonably
simple for users.
My first goal is to hide wxPrintout that makes things rather complicated.

We could create a printing class with a Print() method to start printing
and a virtual PrintPage() method to be implemented by descendant classes.
When printing this class could create a wxPrintout and the
wxPrintout::PrintPage() function could call the same function in the new
class.

The user's code is almost surely inside a class: just derive the user's
class from the printing class, add the PrintPage() implementation and
call the Print() method.

This is just a quick explanation: feel free to ask for mere details.

Do you think that this could be a good idea?

Regards

Fulvio

Vadim Zeitlin

unread,
Sep 18, 2023, 5:35:05 PM9/18/23
to wx-u...@googlegroups.com
On Mon, 18 Sep 2023 16:45:15 +0200 Fulvio Senore wrote:

FS> My first goal is to hide wxPrintout that makes things rather complicated.

Well, wxPrintout is exactly the class which provides the virtual method
allowing to print the page...

FS> We could create a printing class with a Print() method to start printing
FS> and a virtual PrintPage() method to be implemented by descendant classes.

... so it's not obvious how exactly will this class differ from wxPrintout.

FS> The user's code is almost surely inside a class: just derive the user's
FS> class from the printing class, add the PrintPage() implementation and
FS> call the Print() method.

Again, I don't really understand how is this different from deriving it
from wxPrintout?

Fulvio Senore

unread,
Sep 20, 2023, 6:00:10 AM9/20/23
to wx-u...@googlegroups.com


Il 18/09/2023 23:35, Vadim Zeitlin ha scritto:

> FS> The user's code is almost surely inside a class: just derive the user's
> FS> class from the printing class, add the PrintPage() implementation and
> FS> call the Print() method.
>
> Again, I don't really understand how is this different from deriving it
> from wxPrintout?
>

For example, let's say that I want to print three lines of text at a
size of 10 points.

It is a trivial task that now requires to:
- set a printer up
- create a new class derived from wxPrintout
- find a way to make a 10 point text print as 10 point (something like
black magic) in this new class
- make available the text to this class
- print the text in the printout class

With my proposal the task would require to:
- derive the current class also from the new printing class (just a few
chars since there is multiple inheritance)
- add a PrintPage() method that prints the rows
- call the inherited Print() method

Again, the main advantage is not having to do with the printout concept
and all the black magic needed to make it work.
This is not aimed to people that have already successfully printed some
text: they already know how to do it.
The idea is to save some time and some headaches to people that has
never printed before.

Best regards

Fulvio

Vadim Zeitlin

unread,
Sep 29, 2023, 12:01:43 PM9/29/23
to wx-u...@googlegroups.com
On Wed, 20 Sep 2023 12:00:02 +0200 Fulvio Senore wrote:

FS>
FS>
FS> Il 18/09/2023 23:35, Vadim Zeitlin ha scritto:
FS>
FS> > FS> The user's code is almost surely inside a class: just derive the user's
FS> > FS> class from the printing class, add the PrintPage() implementation and
FS> > FS> call the Print() method.
FS> >
FS> > Again, I don't really understand how is this different from deriving it
FS> > from wxPrintout?
FS> >
FS>
FS> For example, let's say that I want to print three lines of text at a
FS> size of 10 points.
FS>
FS> It is a trivial task that now requires to:
FS> - set a printer up
FS> - create a new class derived from wxPrintout
FS> - find a way to make a 10 point text print as 10 point (something like
FS> black magic) in this new class
FS> - make available the text to this class
FS> - print the text in the printout class
FS>
FS> With my proposal the task would require to:
FS> - derive the current class also from the new printing class (just a few
FS> chars since there is multiple inheritance)
FS> - add a PrintPage() method that prints the rows
FS> - call the inherited Print() method
FS>
FS> Again, the main advantage is not having to do with the printout concept
FS> and all the black magic needed to make it work.

Sorry, I am not convinced at all. The main (only?) difference is "find a
way to make a 10pt text print as 10pt" but you don't tell how is it going
to work in the second case. Surely if we can find a way to work in it, we
could make it work with wxPrintout too? And, of course, it would be great
if we could do it (and I think we should be able to), but this doesn't seem
to require any new API.

I.e. I think your class (how would you call it, BTW?) just seems much
simpler than wxPrintout to you because you came up with this idea, but to
me it seems exactly the same as a combination of wxPrinter and wxPrintout,
i.e. it looks potentially even complicated.

Or, IOW, your class could be implemented by just inheriting from the
existing wxPrintout. In fact, I'd encourage you to try doing it like this
and see what does it give. If the resulting API is simpler we could well
call this wxSimplePrintout or something like this and include it in wx.
Reply all
Reply to author
Forward
0 new messages