I would like to create a overridden picturebox control that accepts a colormatrix as a property, and when the picturebox is drawn it uses that colormatrix. This is to cut down on drawimage GDI calls that are slowing down my app. I would love to turn 2 into 1, and cut down form 3 image objects to 1. But when decompiling the Windows.Forms.PictureBox I find that its onPaint method is an override of the Windows.Forms.Control's onPaint method and its don't a hefty amount of sealed work that I can't seem to compile. here is the original onPaint

protected override void OnPaint(PaintEventArgs pe)
        {
            if (this.pictureBoxState[0x20])
            {
                try
                {
                    if (this.WaitOnLoad)
                    {
                        this.Load();
                    }
                    else
                    {
                        this.LoadAsync();
                    }
                }
                catch (Exception exception)
                {
                    if (System.Windows.Forms.ClientUtils.IsCriticalException(exception))
                    {
                        throw;
                    }
                    this.image = this.ErrorImage;
                }
            }
            if (this.image != null)
            {
                this.Animate();
                ImageAnimator.UpdateFrames();
                Rectangle rect = (this.imageInstallationType == ImageInstallationType.ErrorOrInitial) ? this.ImageRectangleFromSizeMode(PictureBoxSizeMode.CenterImage) : this.ImageRectangle;
                pe.Graphics.DrawImage(this.image, rect);
            }
            base.OnPaint(pe);
        }

and here is what I want it to look like

protected override void OnPaint(System.Windows.Forms.PaintEventArgs pe)
        {
            if (base.pictureBoxState[0x20])
            {
                try
                {
                    if (this.WaitOnLoad)
                    {
                        this.Load();
                    }
                    else
                    {
                        this.LoadAsync();
                    }
                }
                catch (Exception exception)
                {
                    if (System.Windows.Forms.ClientUtils.IsCriticalException(exception))
                    {
                        throw;
                    }
                    base.image = this.ErrorImage;
                }
            }
            if (base.image != null)
            {
                base.Animate();
                ImageAnimator.UpdateFrames();
                Rectangle rect = (base.imageInstallationType == base.ImageInstallationType.ErrorOrInitial) ? base.ImageRectangleFromSizeMode(PictureBoxSizeMode.CenterImage) : base.ImageRectangle;
                if (PaintCM == new ColorMatrix())
                {
                    pe.Graphics.DrawImage(base.image, rect);
                }
                else
                {

                    ImageAttributes ia = new ImageAttributes();
                    ia.SetColorMatrix(PaintCM);
 
                    pe.Graphics.DrawImage(base.image, rect, 0, 0, Image.Width, Image.Height, GraphicsUnit.Pixel, ia);
                }
            }
            base.OnPaint(pe);
        }

Problem is, It won't compile because those objects it want to use are sealed internal classes to the Windows.Forms library.

So is there anything I can do? I don't want to start from scratch on a control that does this because I have already done EXTENSIVE work from a picturebox control base and I don't want to ruin the hours I spent on all that code, I'm afraid I won't be able to pull up the same centering zoom effect.

But any input would be appreciated. I will do it from scratch if I have to. I just really would like not to, if you know what I mean.

Recommended Answers

All 4 Replies

What is PaintCM and why are you instantiating an instance of it in the paint event: if (PaintCM == new ColorMatrix()) ? I don't understand the conditions which you're trying to change the painting event for really. Try to explain your problem a little more and hopefully we can figure it out!

that's not the problem at hand, the problem isn't what I changed, The problem is that I can't access parts of the original paint event that I want to modify, because they are sealed.

the code I added works alone, PainCM is a colormatrix variable, (PaintCM == new ColorMatrix()) simply says if the variable hasn't been set to a value, don't use it.

The code I added uses a colormatrix when drawing the image to the control, thus eliminating the need to modify the original image during a preview of the changes.

The problem is, If I override the onPaint event of a picturebox control, I can add to the original paint, or I can remove it, But I cannot modify it, as I dont have access to System.Windows.Forms.ClientUtils.IsCriticalException(exception) (although I could find away around that one I think) but I don't have access to this.pictureBoxState[0x20] nor can I access this.Animate(); , ImageAnimator.UpdateFrames(); , this.imageInstallationType , this.ImageRectangleFromSizeMode() , this.ImageRectangle; the modifications I made in the override are sound, I just can't access those because they are private internal objects of the picturebox, and I tried decompiling and recompiling a changed version of the picturebox control, but it won't build because the protection level of the objects it needs say there are sealed to the windows.Forms lib.

So how can I modify just a few lines of the paint method of the picturebox?

Ah I see. To my knowledge the only way you can do that is to use reflection which is a very bad idea for controls since it is inherently slow. I took a look at the 3rd party controls I use that have fancy graphics/looks and they designed all of their controls (panel, button, picturebox, etc) from Control and ignored the similar control types provided in the .NET framework. I have a lot of respect for the guys at developer express so if they started all of their controls from Control I would guess that they ran in to the same limitation and wrote their controls from scratch.

I think you are right:

I will do it from scratch if I have to. I just really would like not to, if you know what I mean.

commented: Thanks, I feared that was the case. +2

Thanks sknake, I though I might have to do that, so I already started a simple one just to see what kind of performance I get out if it. And it works great. So I guess I will set off to make a custom control for this.

Just to make a point, making a simple picturebox doesn't concern me, but I created a picturebox control inheriting from picturebox that supports a crop and a uncrop/recrop feature that I put a lot of work into, and now I must relate that to a new control.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.