c# - make rectangle around control get transparent

I have a Circle class that draws a circle in a blank rectangle, which is put in a picturebox, then I use the rectangle to move the drawing in the picturebox.
The problem is I can't get the rectangle transparent, I just get it opaque.

Please take a look at my Circle class attached code:
protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            if (this.Width != this.Height)
                this.Width = this.Height;
            pen.Color = BorderColor;
            pen.Width = BorderWidth;
            Create(e.Graphics, new RectangleF(0, 0, this.Width - 3, this.Height - 3), pen, Color.FromArgb(0, FillColor.R, FillColor.G, FillColor.B));           
        }

        private void Create(Graphics gfx, RectangleF bounds, Pen drawPen, Color fillColor)
        {
            int strokeOffset = Convert.ToInt32(Math.Ceiling(drawPen.Width));
            bounds = RectangleF.Inflate(bounds, -strokeOffset, -strokeOffset);
            if (bounds.Width < 1)
                bounds.Width = 1;
            if (bounds.Height < 1)
                bounds.Height = 1;
            drawPen.EndCap = drawPen.StartCap = LineCap.Round;

            GraphicsPath gfxPath = new GraphicsPath();
            gfxPath.AddArc(bounds, 0, 360);
            gfxPath.CloseAllFigures();
            gfx.SmoothingMode = SmoothingMode.AntiAlias;
            gfx.FillPath(new SolidBrush(Color.FromArgb(0, FillColor.R, FillColor.G, FillColor.B)), gfxPath);
            gfx.DrawPath(drawPen, gfxPath);
        }

Open in new window

LVL 1
dnwxAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

spuleCommented:
If you want to make a control transparent, you need to choose a color that is not used in the control (I guess you can use Color.Cyan or Color.Magenta). Then you fill your rectangle with this color and you set your control's TransparencyKey to the same color.
0
CuteBugCommented:
I would suggest you keep your bounding rectangle and the circle in two separate GraphicsPath and call FillPath method for only the Graphics Path containing the circle.

Have a look at the attached code.
        private void Create(Graphics gfx, RectangleF bounds, Pen drawPen, Color fillColor)
        {
            int strokeOffset = Convert.ToInt32(Math.Ceiling(drawPen.Width));
            bounds = RectangleF.Inflate(bounds, -strokeOffset, -strokeOffset);
            if (bounds.Width < 1)
                bounds.Width = 1;
            if (bounds.Height < 1)
                bounds.Height = 1;
            drawPen.EndCap = drawPen.StartCap = LineCap.Round;

            GraphicsPath gfxPath = new GraphicsPath();
            gfxPath.AddArc(bounds, 0, 360);
            gfxPath.CloseAllFigures();
            gfx.SmoothingMode = SmoothingMode.AntiAlias;
            gfx.FillPath(new SolidBrush(Color.FromArgb(0, FillColor.R, FillColor.G, FillColor.B)), gfxPath);
            gfx.DrawPath(drawPen, gfxPath);

            // Draw the rectangle
            gfx.DrawRectangle(drawPen, bounds);
        }

Open in new window

0
dnwxAuthor Commented:

here you are 2 screenshot.

Please note that what I want to do is to hide that white rectangle. In other words, I want the circles to get interlaced.

First one is my old code.
Second one is using CuteBug's code.

any clues?

spule: I can't find TransparencyKey propertie in other control than Form.
picturebox1.jpg
0
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

dnwxAuthor Commented:
second printscreen:


picturebox2.jpg
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
dnwxAuthor Commented:
Wow Idle_Mind...
thank you!
Your code is incredibly better than the one which this irresponsible fired guy left behind.

I still got 3 questions for you
1) is it possible for correcting my code or at least keep my structure, at least for today? (purpose is below).
2) What changes do I have to do to fill the ellipses with a different color in both your codes?
2) How to set it antialias in both your approachs? I know about smoothingmode, but I'm not sure how to use in your codes.

Unfortunatelly I'm not sure I'll be able to change the whole code until tomorrow and also fix the other bunch of bugs...
even because originally I'm no c# nor .net developer... "became" c# dev since 4 days ago, when I forcedly inherited this project (because the the other guy spent all project money and got it kind 4 months late without producing 70% of the software). In few words: I'm screwd up.
But I'll sure use your code as soon as possible to turn this software into something really nice, beautiful and usable.

thank you a lot... I'll give you the points for sure.
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
In my example, the middle of the ellipses are transparent because they are actually being "removed" from the control.  This is done by setting the REGION property of the control to the GraphicsPath containing just the portions of the control I want to keep visible.   The parts of the control that are not in the GraphicsPath are CLIPPED and not drawn at all.  It's as if the control doesn't exist outside the GraphicsPath.  In fact, when you click somewhere not on the ellipse (or the handles) the mouse is actually clicking on whatever is underneath or behind the control.

As far as color goes, are you wanting to changing the color of the ellipse itself?...or fill the interior of the ellipse?

Not sure about aliasing the controls edges itself...
0
dnwxAuthor Commented:
I want to fill the ellipse inside with other color different than the border color.

Understood the region an clipping thing, thanks again!
0
CuteBugCommented:
Hi dwnx,
      with my code provided, I am getting a rectangle with transparent fill and only the ellipse is filled.

      I have attached the screenshot and the code which I used.
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        if (this.Width != this.Height)
            this.Width = this.Height;
        Pen pen = new Pen(Brushes.Black, 2F);
        Create(e.Graphics, new RectangleF(100, 100, 100, 100), pen, Color.Blue);
        Create(e.Graphics, new RectangleF(150, 150, 100, 100), pen, Color.Red);
    }

    private void Create(Graphics gfx, RectangleF bounds, Pen drawPen, Color fillColor)
    {
        int strokeOffset = Convert.ToInt32(Math.Ceiling(drawPen.Width));
        bounds = RectangleF.Inflate(bounds, -strokeOffset, -strokeOffset);
        if (bounds.Width < 1)
            bounds.Width = 1;
        if (bounds.Height < 1)
            bounds.Height = 1;
        drawPen.EndCap = drawPen.StartCap = LineCap.Round;

        GraphicsPath gfxPath = new GraphicsPath();
        gfxPath.AddArc(bounds, 0, 360);
        gfxPath.CloseAllFigures();
        gfx.SmoothingMode = SmoothingMode.AntiAlias;
        gfx.FillPath(new SolidBrush(fillColor), gfxPath);
        gfx.DrawPath(drawPen, gfxPath);

        // Draw the rectangle
        gfx.DrawRectangle(drawPen, bounds.Left, bounds.Top, bounds.Width, bounds.Height);
    }
}

Open in new window

Circle-Rect.JPG
0
dnwxAuthor Commented:
CuteBug:

I can't figure out how to use your code inside my Circle class, I mean, how to do make it work without writing hardcoded code in the picturebox Paint method.

Is there a way that I can put this code dinamically in the picturebox Paint method everytime I click the CreateCircle button?

Just to make it clear: I need to move and resize those circles (it already works this way with my old code)..

Puting your code hardcoded in the picturebox's paint method works perfectly as your printscreen shows.
0
CuteBugCommented:
There is a way to solve your problem.

First, in your Circle class, maintain the location and size of the Circle. do have a method in your Circle class (say Render) which will take Graphics as an input.
In your Form (or your main class) which contains the picturebox, maintain a List of your Circle class.
In the Paint method of the PictureBox, you will get the Graphics class, e.Graphics . Now iterate through each Circle in the List and call the Render method of that object while passing e.Graphics as the argument.

Now whenever you move or resize any of your Circle, all you need to do it update that Circle's values in the List and call the Invalidate() method of the PictureBox which will redraw all the Circles.

In order to avoid flickering, make your Form and Picturebox double buffered.
Check these links for double buffering
http://www.bobpowell.net/doublebuffer.htm
http://www.codeproject.com/KB/graphics/DoubleBuffering.aspx
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
So you have two basic options:
(1) Each circle is its own control.  This requires the control to be clipped, though, by setting the Region() property if you want to be able to overlap the things since the underlying basis for controls is a rectangle.  The advantage here is that you can get mouse events for each control neatly encapsulated in the controls themselves.
(2) Everything is drawn directly into the PictureBox.  Since you are only drawing the circles you don't need to worry about the overlapping issue as they will do this by default.  The disadvantage is that you must manually perform all of your hit-testing to determine if the mouse is over a circle.  The code for allowing selection and manipulation of the circles becomes a lot messier.
0
CuteBugCommented:
Hi Idle_Mind,
      I have a solution for (2)

      Three event must be considered for the handling selection and manipulation of the circle objects
      1. MouseDownEvent
      2. MouseMoveEvent
      3. MouseUpEvent

      The Circle objects will be maintained in a List<Circle>, say, DrawnCircles.

      We must also maintain the reference to the Circle being currently manipulated, say, CurrentCircle.

      The Circle class must also have the following:
      1. An enum called ManipulationMode having three values { RESIZING, MOVING, NONE }
      2. A private variable called m_ManipulationMode of type ManipulationMode.
      3. A method called IsManipulated(Point pt) - This will determine whether the given point lies within one of the handles of the Circle (if yes then set m_ManipulationMode as RESIZING) or within the Circle (If yes then set m_ManipulationMode as MOVING). This method will return true if the value of m_ManipulationMode is RESIZING/MOVING else it will return false.
      4. A member variable called m_PrevPoint of type Point. Set m_PrevPoint = pt (in the IsManipulated method)
      5. A method called HandleManipulation(Point pt) - which will do the resizing/moving based on the new Point being provided.
      6. A method called StopManipulation() which will set the m_ManipulatedMode to NONE.

      Now in the main Form, handle the MouseDown, MouseMove and MouseUp events of the PictureBox.

      In the MouseDown eventHandler, iterate through each Circle in the DrawnCircles list and call the IsManipulated method of each Circle. If any Circle's method returns true then set CurrentCircle equal to that Circle.

      In the MouseMove eventHandler, check if the mouse is down and CurrentCircle is not null, then call the HandleManipulation method of that Circle, passing the point obtained.

      In the MouseMove eventHandler, check if the CurrentCircle is not null, then call the StopManipulation method of that Circle.

      This should do it.
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
That'll work...

In fact, in the SAME PAQ I referenced earlier that demonstrates method #1, I also posted a simple version of method #2:
http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_25089847.html#26428585
0
CuteBugCommented:
Oh.. ok!

Well, previously I did not go through the link you provided, Idle_Mind.

Anyways I hope dnwx would now have got a good idea for the solution to his problem.

cheers
CuteBug
0
dnwxAuthor Commented:
CuteBug and Idle_Mind,

I'm still reading and "digesting" all information.

Just would like you to know you really helped me a lot.

I'll give you my feedback as soon as possible (i'm at worktime now).

Thank you!!!
0
dnwxAuthor Commented:
dudes,

sorry for the delay.

I've done the Region thing, because using one of the other ideas would require to change a lot of code, spread all over the software, it would be almost the same as doing it from zero mark.

Unfortunatelly, even the simpler region code get's a lot ugly because of aliasing. And I couldn't find a way to smooth it.
Any Ideas on how to smooth the clipped border, or should I just give up and start it using your ideas/code?


Here you are a printscreen showing the aliasing thing.
sample.png
0
CuteBugCommented:
In the OnPaint() method, try setting the InterpolationMode and SmoothingMode properties of e.Graphics.

Set e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
and e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
0
dnwxAuthor Commented:
Thank you CuteBug and Idle_Mind. You helped me a lot. I would give you 500 points if I could, but I had to share between you both. I'm sticking with Idle_Mind's code, so I gave him more points.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.