Page 1 of 1

Images/Controls + Text Boxes - transparent background colour

Posted: Mon May 29, 2006 10:19 am
by uketernity
Hi,

Ive searched through the forums to try and find a solution to this, but so far have not found a solution.

This is my situation:

I have an image painted onto the back of my frame using DC, now this works fine, however, the problem comes when putting in.
StaticBitmap images with transparency - the transparent regions of the image show up with the background colour of the frame (grey) and not the DC image painted on.
controls that dont have square corners - the region of the square that the control "occupies" is grey, ie, with a radio button, each corner has a grey part.
Text boxes. The background to the text is the background colour of the wxFrame.

I have found a kind of solution that draws the text labels onto the background in the onPaint method and this works, however, I cant do the same thing for images as my programs needs to hide them

Code: Select all

Image1->Show(false);
as part of its operation. Also, when you hide the image, the image correctly dissappears, however the region that it takes up in the frame is grey for a split second and then is overwritten with the background image to the frame.

Does anyone know how to fix this problem?

Thanks.

Oli

Posted: Tue May 30, 2006 9:23 am
by Cursor
Perhaps it do that beacause you use wxCLIP_CHILDREN style for your frame.
Indeed, this style force to not repaint the background under children.
test without this style.

Posted: Tue May 30, 2006 9:29 am
by uketernity
Hi,

Unfortunately im not using the wxClip_Children style for my frame. Any other ideas?

Oli

Posted: Tue May 30, 2006 4:28 pm
by wxjonas
Hi

You shouldn't put your controls directly on the frame, instead put a wxPanel on the frame, and your controls on the panel. This is more crossplatform safe, and make sure things like taborder works.

As for painting a background, look at wxEraseEvent.

HTH
/Jonas

Posted: Tue May 30, 2006 6:02 pm
by micros
Anyone please correct me if I'm wrong, but I don't think there is a way one could make wxStaticBitmap honour alpha channel (at least not a portable one).
uketernity wrote:I have found a kind of solution that draws the text labels onto the background in the onPaint method and this works, however, I cant do the same thing for images as my programs needs to hide them.
Why not? You can have bitmap-position-visibility tuples and refresh parts of the window that need it when anything changes. Here's a simple class I would write to move this functionality out of the containing window:

Code: Select all

class PositionedBitmap
{
  public:
    PositionedBitmap(wxWindow* parent, const wxPoint& pos, wxBitmap bmp)
      : m_parent(parent), m_pos(pos), m_bmp(bmp), m_shown(false)
    { }

    wxPosition getPosition() const
    {
      return m_pos;
    }

    wxSize getSize() const
    {
      return wxSize(m_bmp.GetWidth(), m_bmp.GetHeight());
    }

    void show(bool show = true)
    {
      if (show != m_shown) {
        wxRect rc(m_pos, getSize());
        m_shown = show;
        m_parent->Refresh(true, &rc);
      }
    }

    bool isShown() const
    {
      return m_shown;
    }

    void drawOnto(wxDC& dc) const
    {
      dc.DrawBitmap(m_bmp, m_pos.x, m_pos.y, true);
    }

  private:
    wxWindow* m_parent;
    wxPoint m_pos;
    wxBitmap m_bmp;
    bool m_shown;
};
It's not even a control, but a mere envelope for all the required information. The containing window will just keep some instances and in it's onPaint draw each of them like:

Code: Select all

if (pb.isShown()) pb.drawOnto(dc);
Calling pb.show() in response to any other event will cause repainting of the damaged area.

Posted: Tue May 30, 2006 11:27 pm
by amititz
Hi,

I'm also having the same problem. What do you suggest I can do with controls such as radio buttons and text labels? I'm basically trying to lay them out using a structure of nested sizers and panels, but the background color of the frame keeps showing as the background of the text labels, radio buttons, etc., instead of the badkground IMAGE of the frame.

Posted: Wed May 31, 2006 7:22 pm
by uketernity
Im with you on that one. I dont really understand how the class method works.

The wxStaticBitmaps do support an transparency, and this works fine, however, the transparent regions of the image do not show the image pained onto my frame, instead, they show the background colour. Its as if the background to the frame is being drawn after the controls are drawn, and as such, the controls adopt the frame bg colour before the background image is drawn on.

Refering to my previous example about the region the control/image takes up being grey for a split second when you use

Code: Select all

Image1->Show(false);
is shown in these 2 images:

Image shown:
Image

Image hidden:
Image

Please, someone help me :) thanks.

Oli

Posted: Thu Jun 01, 2006 9:47 am
by uketernity
Hi micros,

I looked through your class and managed to work out what its doing, however, I need to know how to create my image in the first place, how do you do that?

Could you give me an example of how to do this?

Thanks.

Oli

Posted: Thu Jun 01, 2006 11:15 am
by micros
uketernity wrote:I looked through your class and managed to work out what its doing, however, I need to know how to create my image in the first place, how do you do that?

Could you give me an example of how to do this?
You mean how to use the class I posted? Have to warn you it's just an untested suggestion :)

First, since you're going to need a lot of images, add a default constructor and an initializer method. If you didn't have these, everything would have to be set up in the initialization section of the frame's ctor, and (1) I think loading bitmaps is too complex to put in there, and (2) MSVC thinks that using this in initialization section is evil. ('f course you could allocate the PositionedBitmaps dynamically, but I always try to avoid too much news and deletes).

Code: Select all

class PositionedBitmap
{
  public:
    // a default constructor, initialize must be called before use!
    PositionedBitmap()
      : m_parent(NULL), m_pos(wxDefaultPosition), m_shown(false)
    { }

    void initialize(wxWindow* parent, const wxPoint& pos, wxBitmap bmp)
    {
      m_parent = parent;
      m_pos = pos;
      m_bmp = bmp;
    }

    // and leave the rest as it was; perhaps you could add some checking
    // as for (m_parent != NULL) and m_bmp.Ok() at the right places
    // ...
};
Now you'll have a bunch of these in your frame.

Code: Select all

class MyFrame : public wxFrame
{
  // ...

  PositionedBitmap m_imgVolume;
  PositionedBitmap m_imgSub;
  PositionedBitmap m_imgFader;
  PositionedBitmap m_imgCenter;
  // and so on

  std::vector<PositionedBitmap*> m_images; // will explain later
};

// in the frame's ctor, you'll initialize them
MyFrame::MyFrame(...)
{
  // ...
  m_imgVolume.initialize(this, wxPoint(30, 150), wxBitmap(wxT("volume.png"), wxBITMAP_TYPE_PNG));
  m_images.push_back(&m_imgVolume);
  m_imgSub.initialize(this, wxPoint(50, 150), wxBitmap(wxT("sub.png"), wxBITMAP_TYPE_PNG));
  m_images.push_back(&m_imgSub);
  // etc.
}
You will then want to draw some/all of them in MyFrame::OnPaint. This is why I created the m_images vector. It's not absolutely necessary -- without it, you would just draw m_imgVolume, then m_imgSub, and so on. But adding a new button would require changes to OnPaint(); with the vector, you only put one more line after initialize() in the ctor. Now we can draw them all in a loop. I don't know how your OnPaint() is implemented, guess it can't be far from this:

Code: Select all

void MyFrame::OnPaint(wxPaintEvent& event)
{
  wxBufferedPaintDC dc(this);

  // draw background and other stuff
  // ...

  // now draw the hideable images
  for (size_t i = 0; i < m_images.size(); ++i) {
    if (m_images[i]->isShown())
      m_images[i]->drawOnto(dc);
  }
}

Posted: Thu Jun 01, 2006 3:39 pm
by uketernity
Hi micros,


Ive tried implementing your solution, while I understand what it does, I cant seem to get it to work. Would you be kind enough to drop it into some source files and send them to me at all?

Im a bit stuck.

Thanks.

Oli