Thread: Transparent Color

  1. #1
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853

    Transparent Color

    I have made the same topic months ago, but left the project and now trying to redo it again.
    Problem: I have a panel with a BackgroundImage. I want to make a color (lets say white) transparent, thus that color not to be painted at all.

    I googled I tried and failed. The only thing that seemed to work is when you use the Graphics.DrawImage() method and use the ColorMatrix and ImageAttribute classes to give some transparency on the image. But you cannot choose a specific color to make transparent, you can only work on the RGBA channels, which isn't helpful in my situation.

    So what can I do here?

  2. #2
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    Bitmap.MakeTransparent

    Code:
            Constructor()
            {
                this.mBitmap = new Bitmap("TransparentImage.png");
                this.mBitmap.MakeTransparent(this.mBitmap.GetPixel(0, 0));
            }
            protected override void OnPaint(PaintEventArgs e)
            {
                if (this.mBitmap != null)
                {
                    e.Graphics.DrawImage(this.mBitmap, 100, 0);
                }//if  
            }
    Attached are the screenshot of the form, and the original image.
    Woop?

  3. #3
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    That doesn't really work. What it does it changes the color to Color.Transparent. Which Color.Transparent is just a color defined (the back color of the form). If you put two panels on each other you will see that it doesn't work as it should.

  4. #4
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    I see what you are saying now.

    Now I am intrigued. I will do some research and see what I can come up with.
    Woop?

  5. #5
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Quote Originally Posted by C_ntua View Post
    That doesn't really work. What it does it changes the color to Color.Transparent. Which Color.Transparent is just a color defined (the back color of the form). If you put two panels on each other you will see that it doesn't work as it should.
    My advice remains the same as last time -- don't put two panels on top of each other. Use one large panel for the whole area and blit the individual image(s) onto a single bitmap (using SetColorKey) and display that final combined bitmap on the single panel.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  6. #6
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401
    What's wrong with TransparencyKey?
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  7. #7
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    That doesn't work either. What it does it makes the part of the panel with that color transparent. Which makes you see through the window itself.
    I would like a TransparencyKey property for the Panel, which I don't see it existing. I have no idea why...

    I found a way to do what I want, not the best way though
    Code:
    public class TPanel : Panel
        {
            public TPanel()
            {
            }
            protected override CreateParams CreateParams
            {
                get
                {
                    CreateParams cp = base.CreateParams;
                    cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
                    return cp;
                }
            }
            public void InvalidateEx()
            {
                if (Parent == null)
                    return;
                Rectangle rc = new Rectangle(this.Location, this.Size);
                Parent.Invalidate(rc, true);
            }
            protected override void OnPaintBackground(PaintEventArgs e)
            {
            }
            protected override void OnMove(EventArgs e)
            {
                base.OnMove(e);
                InvalidateEx();
            }
            protected override void OnPaint(PaintEventArgs e)
            {
                Image image = new Bitmap(@"C:\Users\Gift\Desktop\image.gif");
                e.Graphics.DrawImage(resizeImage(image, Size), 0, 0);
            }
        }
    The key is InvalidateEx() which fixes the control that is below the existing control. There should be a better place to call it rather than OnMove. Any ideas???
    This way also is bad because there are too jobs done. One is painting the Panel and then the parent panel. So while you move a panel there will be some flickering.

    Also, I have to use XnView to set a transparency color on the GIF image. So it restricts what images I can use. I am sure there is a way to do so from the .NET library.

    EDIT: There is actually a problem in this code. The parent control seems to be painted on top of the child control...
    Last edited by C_ntua; 05-18-2010 at 03:30 PM.

  8. #8
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Quote Originally Posted by C_ntua View Post
    This way also is bad because there are too jobs done. One is painting the Panel and then the parent panel. So while you move a panel there will be some flickering.
    You will never get rid of flickering entirely as long as you're using a panel-over-a-panel approach. If you move or change the upper panel, it will need to redraw both itself and the lower panel, and you can get flickering depending on when those are redrawn.

    The only true way to avoid flickering is to double-buffer, which you can't do when you're trying to use various overlapping elements to create an image.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  9. #9
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    I guess you are right. Using the engine in the first place was an error, should use something I have more control.

    But for my purpose the flickering is OK. I just have to fix the problem of the panel appearing underneath the other. The problem is that the panel underneath the panel I am moving is drawn last, instead of first. So even though the moving panel is on top of the other it appears it is on the bottom.

    In any case, is there a good way to do this? I tried also various SetStyles() but I don't find anything that works more a moving panel.

  10. #10
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    I added this
    Code:
           
    protected override void OnMouseUp(MouseEventArgs e)
    {
                base.OnMouseUp(e);
                Invalidate();
     }
    And it sort of works. But I don't really get the Invalidate() system here. If I do
    Code:
           
    protected override void OnMove(EventArgs e)
    {
          base.OnMove(e);
          InvalidateEx();
          Invalidate();
    }
    Then it doesn't work.
    I have a drag logic for the panel. You drag it it moves, so when you release the mouse the OnMouseUp() is fired and the panel is no longer moving.

  11. #11
    Registered User
    Join Date
    Mar 2009
    Location
    england
    Posts
    209
    If you have flickering you could try setting the panel's DoubleBuffer property to true.

  12. #12
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Well, my biggest problem is that this method doesn't really work. I am trying to "cheat" my way through. Obviously there is a problem with the whole transparency thing and I cannot find a good way to do it.
    I used the most recommended example I could find around the web, which is what I posted. I works great but only for one transparent panel. With my fix, it works for two. But if I have three lets say panel A, B and C, and panel A is on top of B, panel B on top of C, then this method doesn't work. What happens is that it paints first A, then B and then C. C will come in front again (cause of the OnMouseUp() function), but B will be painted on the bottom.

    Aaah, the whole system is just not meant to be used like this. The problem is that I want a fully transparent Panel. That doesn't have a BackColor at all. And the Color.Transparent or a color with a zero Alpha channel even with SupportTransparentBackground option enabled doesn't work. Except if I am missing something??

    I will try further cheating my way. I kind of need to be able to display a circle or a hexagon shaped panel...

  13. #13
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Code:
            protected override void OnMouseUp(MouseEventArgs e)
            {
                base.OnMouseUp(e);
                if (!transparency) { return; } 
                foreach (Pawn p in Game.pawns)
                {
                    if (!p.isDocked())
                        p.pic.Invalidate();
                }
            }
    I used a code like this. Which just enables me to set "docked" transparent panels. If it is docked it is like a background transparent panel.

    So, for further use, this is a class I suggest for a "transparent moving panel".
    Docked is a panel that you want to be set to the background. The transparency variable is used to set the whole feautre On/Off. If the TPanels are not docked then there can be troubles on their z-order evaluation, but by docking you should be able to have only one un-docked panel.
    Finaly, the resize Image is used in order to make the BackgroundImage the appropriate size of the panel so you can paint it with the DrawImage() method, since the Stretch layout won't work here.

    Code:
    public class TPanel : Panel
        {
            public bool transparency;
            public bool docked;
            public TPanel()
            {
                transparency = false;
                docked = false;
            }
            protected override CreateParams CreateParams
            {
                get
                {
                    if (!transparency) return base.CreateParams;
                    CreateParams cp = base.CreateParams;
                    cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
                    return cp;
                }
            }
            void InvalidateEx()
            {
                if (Parent == null)
                    return;
                Rectangle rc = new Rectangle(this.Location, this.Size);
                Parent.Invalidate(rc, true);
            }
            protected override void OnPaintBackground(PaintEventArgs e)
            {
                if (!transparency) { base.OnPaintBackground(e); } 
            }
            protected override void OnMove (EventArgs e)
            {
                base.OnMove(e);
                if (!transparency) { return; } 
                InvalidateEx();
            }
            protected override void OnMouseUp(MouseEventArgs e)
            {
                base.OnMouseUp(e);
                if (!transparency) { return; } 
                foreach (Panel p in AllYourPanels)
                {
                    if (!p.docked)
                        p.Invalidate();
                }
            }
            protected override void OnPaint(PaintEventArgs e)
            {
                if (!transparency) { base.OnPaint(e); return; } 
                if (BackgroundImage != null)
                    e.Graphics.DrawImage(BackgroundImage, 0, 0);
                else
                    e.Graphics.FillRectangle(new SolidBrush(BackColor), 0, 0, Size.Width,    Size.Height);
            }
    
            public static Image resizeImage(Image imgToResize, Size size)
            {
                int sourceWidth = imgToResize.Width;
                int sourceHeight = imgToResize.Height;
    
                float nPercent = 0;
                float nPercentW = 0;
                float nPercentH = 0;
    
                nPercentW = ((float)size.Width / (float)sourceWidth);
                nPercentH = ((float)size.Height / (float)sourceHeight);
    
                if (nPercentH < nPercentW)
                    nPercent = nPercentH;
                else
                    nPercent = nPercentW;
    
                int destWidth = (int)(sourceWidth * nPercent);
                int destHeight = (int)(sourceHeight * nPercent);
    
                Bitmap b = new Bitmap(destWidth, destHeight);
                Graphics g = Graphics.FromImage((Image)b);
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
    
                g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
                g.Dispose();
    
                return (Image)b;
            }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Towr of Hanoi move the disc
    By WatchTower in forum C Programming
    Replies: 9
    Last Post: 07-17-2009, 03:48 AM
  2. Critique my lighting model.
    By psychopath in forum Game Programming
    Replies: 4
    Last Post: 08-12-2006, 06:23 PM
  3. egavga.bgi problem
    By sunil21 in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 09-22-2003, 05:06 PM
  4. My opinion on skin color
    By Leeman_s in forum A Brief History of Cprogramming.com
    Replies: 8
    Last Post: 07-11-2003, 12:12 PM
  5. Just one Question?
    By Irish-Slasher in forum C++ Programming
    Replies: 6
    Last Post: 02-12-2002, 10:19 AM