wxMemoryDC->SetTextForeground

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Rohit Agarwal
Knows some wx things
Knows some wx things
Posts: 42
Joined: Wed May 19, 2021 11:17 pm
Contact:

wxMemoryDC->SetTextForeground

Post by Rohit Agarwal »

wxMemoryDC->SetTextForegroundColor( wxColour( 255,0,0,255 ) ) // RED
wxMemoryDC->DrawText()

The code works fine on MacOS and GTK and draws the text in red
but on Windows it draws the text in white

Is this a known behaviour that has been patched?

I'm using 3.1.5
PB
Part Of The Furniture
Part Of The Furniture
Posts: 3090
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxMemoryDC->SetTextForeground

Post by PB »

I cannot confirm this on Win10. I am using GIT master but I am not aware of any code change that could affect this.
dc_settextforeground.png
dc_settextforeground.png (2.73 KiB) Viewed 1594 times

Code: Select all

#include <wx/wx.h>

class MyApp : public wxApp
{
public:
    bool OnInit() override
    {
        wxFrame* frame = new wxFrame(nullptr, wxID_ANY, "Test");

        frame->SetBackgroundColour(*wxBLACK);

        frame->Bind(wxEVT_PAINT, [frame](wxPaintEvent&)
        {
            wxPaintDC dc(frame);
            const wxColour clr = wxColour(255,0,0,255);

            dc.SetTextForeground(clr);
            dc.DrawText(clr.GetAsString(wxC2S_CSS_SYNTAX), 5, 5);
        });

        frame->Show();
        return true;
    }
}; wxIMPLEMENT_APP(MyApp);
Does wxDC::GetTextForeground() return the correct colour?

EDIT
Oops, I somehow missed that this is about wxMemoryDC but it still works even with wxMemoryDC:

Code: Select all

#include <wx/wx.h>

class MyApp : public wxApp
{
public:
    bool OnInit() override
    {
        wxFrame* frame = new wxFrame(nullptr, wxID_ANY, "Test");

        frame->SetBackgroundColour(*wxBLACK);

        frame->Bind(wxEVT_PAINT, [frame](wxPaintEvent&)
        {
            const wxColour clr = wxColour(255,0,0,255);

            wxBitmap   bmp(400, 400);
            wxMemoryDC mdc(bmp);
            wxPaintDC  dc(frame);

            mdc.SetTextForeground(clr);
            mdc.DrawText(clr.GetAsString(wxC2S_CSS_SYNTAX), 5, 5);
            dc.Blit(wxPoint(0,0), bmp.GetSize(), &mdc, wxPoint(0,0));
        });

        frame->Show();
        return true;
    }
}; wxIMPLEMENT_APP(MyApp);
Rohit Agarwal
Knows some wx things
Knows some wx things
Posts: 42
Joined: Wed May 19, 2021 11:17 pm
Contact:

Re: wxMemoryDC->SetTextForeground

Post by Rohit Agarwal »

The observed anomalous behaviour is on Windows 10.
I draw to a wxMemoryDC and later blit that to a wxPaintDC.

EDIT: I suspect if a set the pen color it will fix this on windows
PB
Part Of The Furniture
Part Of The Furniture
Posts: 3090
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxMemoryDC->SetTextForeground

Post by PB »

Rohit Agarwal wrote: Sat Jul 10, 2021 3:11 pm The observed anomalous behaviour is on Windows 10.
I draw to a wxMemoryDC and later blit that to a wxPaintDC.
So exactly the same what I showed working in the second code block in my previous post? Can you reproduce the issue with using that code verbatim on your setup? If you cannot you must have some other code affecting this. IIRC, wxMemoryDC (and AFAIK wxBufferedDC which uses it) had issues with setting some attributes.

I do not see how a pen colour should have any effect on this. Is the current font correct?
Rohit Agarwal
Knows some wx things
Knows some wx things
Posts: 42
Joined: Wed May 19, 2021 11:17 pm
Contact:

Re: wxMemoryDC->SetTextForeground

Post by Rohit Agarwal »

My wxMemoryDC and wxPaintDC are not on the stack.
They are newed onto the heap, passed around and deleted.

I do see drawn text in white.
If I change the colour (from red to something else) it has no effect, o/p is still in white.
i.e. I don't think it is a font issue.

I tried setting the pen colour but that did not help either.
I'll investigate further.

I have a dual boot machine Win10/Ubuntu.

The same code, on the same machine with the 2 different OSs has this disparity.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 3090
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxMemoryDC->SetTextForeground

Post by PB »

You did not answer any of my questions I believe relevant to the issue nor did you report if running my code verbatim reproduces the issue (if nothing else to make sure that it is not due to a difference in wxWidgets version): Why? Looking at your codes I understand you are new not only to wxWidgets but also to programming, but still...
Rohit Agarwal wrote: Sat Jul 10, 2021 4:00 pm My wxMemoryDC and wxPaintDC are not on the stack.
While this may be quite unusual it should not cause the issue (I tried, and it does not) unless you have a bug in your code. For example, you need to make sure you create and destroy a wxPaintDC in your wxPaintEvent handler and do not leave it dangling.

wxMemoryDC is quite sensitive about its bitmap, I would make sure the selected bitmap is always valid and not destroyed during lifetime of a wxMemoryDC. However, I still do not see how could it trigger the described behavior.

Anyway, if you want to resolve the issue the usual first step is to reproduce it with the smallest amount of code possible, in other words something like SSCCEs I posted here. When it works in an SSCCE and not in your code, your code does something that causes the issue but as you do not provide it, generally only a debugging psychic can help. Those are quite rare.
Rohit Agarwal
Knows some wx things
Knows some wx things
Posts: 42
Joined: Wed May 19, 2021 11:17 pm
Contact:

Re: wxMemoryDC->SetTextForeground

Post by Rohit Agarwal »

I'll try and isolate the problem as best I can.
I could not use your code verbatim because I use wxMemoryDC * and not wxMemoryDC.
I do think there is a problem,
but it's not really bothering me right now.
What's glaring is the difference in platform level behavior.
Just wanted to check if someone else had already encountered something similar.

Will isolate the problem and post code soon.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 3090
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxMemoryDC->SetTextForeground

Post by PB »

Rohit Agarwal wrote: Sat Jul 10, 2021 4:37 pm I could not use your code verbatim because I use wxMemoryDC * and not wxMemoryDC.
Sorry, verbatim means "exactly as it is", so you could use it and I already explained why you should have.
Rohit Agarwal wrote: Sat Jul 10, 2021 4:37 pm What's glaring is the difference in platform level behavior.
I am not saying that there are no platform differences when using wxWidgets but your difference may be caused in the bug in your code. For example some platform may not be that sensitive to not creating/destroying a wxPaintDC (i.e., on Windows translating to ::{Begin:End}Paint() ) in the paint event handler.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 5315
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxMemoryDC->SetTextForeground

Post by ONEEYEMAN »

Hi,
You shouldn't create a device context on a heap (especially a paint one).
This is a system resource and could cause you trouble like this one.

Please try PB's code and see if it works. If it does - change yours to look like that.

Thank you.
Rohit Agarwal
Knows some wx things
Knows some wx things
Posts: 42
Joined: Wed May 19, 2021 11:17 pm
Contact:

Re: wxMemoryDC->SetTextForeground

Post by Rohit Agarwal »

Not sure this has any bearing,
but I'm getting the PaintDC from the Canvas and not the Frame.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 5315
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxMemoryDC->SetTextForeground

Post by ONEEYEMAN »

Hi,
You shouldn'ty be passing the paint dc around.
Paint DC is for the EVT_PAINT event only.
And because it is a system resource - you shouldn't be deleting it manually.

However since it is a system resource you absolutely have to return it to the original state when you finish painting.

So the code from PB is the way to go and you shouldn't be creating it on the heap, passing it around and leave it in an non-default state.

Please change your code as appropriate.

Thank you.
Post Reply