Graphics overlap avoiding transparence

leorob88

Member
Joined
Dec 31, 2020
Messages
23
Programming Experience
1-3
Hi, I have a problem drawing in a PictureBox.
To summarize and make an example: imagine you have to draw a rectangle at 0, 0 and it's 100x100 pixels; then you have to draw another rectangle 10x10 at the center (which should be at 45, 45 if i'm not mistaken) but the result shall be simply the first rectangle...meaning they both get drawn, you just can't distinguish them (or maybe you can find a way to say "if some of the second shape overlaps the first, don't draw the overlapping part).
Basically, i have to draw in the picturebox with a brush and first I create a region to specify where it shall be drawn and where not.
I have a system in a dictionary to pick up coordinates and dimensions of various rectangles. First of all, in the paint event of the picturebox, i create a graphicspath. Then what i do cyclically is:

- go and pick data for the rectangle, to create it
- i add the rectangle to the graphicspath

Then with the graphicspath created and made with every single rectangle, i state that picturebox.region = new region(graphicspath). It DOES work generally speaking.
MAIN PROBLEM IS: when i get to add and draw rectangles that overlap, in the overlap area they just don't get drawn (but the remaining shape of these rectangles does remain drawn), concretely speaking that area becomes "transparent" (as if not drawn).
I don't understand if this problem goes for the graphicpath or for the region and how to avoid it. Someone adviced me to read about Region class methods but the only methods that seemed to fit (union, intersect and complement) worsen the problem. If i cyclically create a graphicspath, with the given rectangle, and then go for region.complement(graphicspath) (and remember, in this second hypothetic case this is a cycle, so next step will be to recreate a graphicspath to complement in the region), at the end what i get is the picturebox gets for region its full space/dimensions.
I spent hours to search and try solutions, so i really hope you can give me some help or concrete direction.

Edit:
I added an image. Basically the second pic you see (the pink lines) should blink above the map on the left, as you see in the 3rd pic. It blinks, that's just fine. Problem is, for now, it doesn't blink like that, instead (following suggestions here below) it blinks pic1/pic2 and repeat. At the beginning instead, when i got transparent overlaps, it blinked exactly like in the pic3, but yeah, overlapped region became transparent as well.
The way this blink is activated is through a Timer, whenever it is activated (interval 500) it loops back and forth. What i forgot to mention and this may be crucial, is that the blink region is another picture box aside that map. In fact, one picturebox contains the image map, the other picturebox is located over the first and what the Timer does cyclically is:

if (evidenziapunti.visible == true) { evidenziapunti.visible = false; } else { evidenziapunti.visible = true; }
 

Attachments

  • Immagine.png
    Immagine.png
    11.5 KB · Views: 9
Last edited:

JohnH

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
1,265
Location
Norway
Programming Experience
10+
The window region is a collection of pixels within the window where the operating system permits drawing. The operating system does not display any portion of a window that lies outside of the window region.
It is probably better to use Graphics.Clip property if you want to include/exclude areas of drawing.
 

leorob88

Member
Joined
Dec 31, 2020
Messages
23
Programming Experience
1-3
I read as suggested by you, John, unluckily this cannot work for me, not in this basic way. Further details: i set an image in the picturebox, and what i want to do is draw on this image in specific areas. What i get with this advice is that id DOES work for avoiding overlaps. BUT while this areas are drawn (correctly) the picturebox image gets overwritten (that's why i needed to create a region, to draw in specific areas leaving the other image in background visible). so the areas that don't get drawn (they're not in the region i want) become simply "default color" and cover the image. i'll try to see if i can fix this some way, but still thank you again.
 

JohnH

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
1,265
Location
Norway
Programming Experience
10+
That only happens if you use Control.Region, because the control will not paint anything outside that region.
It will not happen with Graphics.Clip, that only affect the part you can draw to.
Maybe you can post a basic code example that shows the problem.
 

leorob88

Member
Joined
Dec 31, 2020
Messages
23
Programming Experience
1-3
This is the paint event of the picturebox after i followed your advice and only draws the image OR the rectangles. The graphicspath this way has no use ( i left it for now just for the sake of being there). Before the change, the 2 rows signed with //THIS were not there, instead there was map.AddRectangle(punto); and after the map.close there was evidenziapunti.region = new Region(map); (evidenziapunti is the picturebox) and i got the overlapsed rectangles as i explained.


GraphicsPath map = new GraphicsPath();
for (int i = 0; i < elencoluoghi.Items.Count; i++)
{
if (evidenzia.ContainsKey(elencoluoghi.Items.ToString()))
{
var param = evidenzia[elencoluoghi.Items.ToString()][risultatigiochi.Text];
Rectangle punto = new Rectangle(new Point(param["x"], param["y"]), new Size(param["larg"], param["alt"]));
e.Graphics.Clip = new Region(punto); //THIS
e.Graphics.FillRegion(new SolidBrush(Color.FromArgb(255, 72, 132)), e.Graphics.Clip); //THIS
}
}
map.CloseFigure();
SolidBrush colora = new SolidBrush(Color.FromArgb(255, 72, 132));
e.Graphics.FillRectangle(colora, 0, 0, 478, 340);
 

JohnH

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
1,265
Location
Norway
Programming Experience
10+
So in a loop you set Clip and Fill that clip (that's pointless because drawing doesn't exceed the clip anyway), then you want to fill a large rectangle? The last Clip still applies so you probably want to change that.
If you want to exclude the previous clips you can do that with Region class, it has methods like Exclude, Intersect and Union.
You can also rearrange the code to fill a large rectangle first and then loop and fill smaller parts on top of that.
Mind you, the whole point of clipping is drawing something that is or could exceed the clip and still be limited to the clip.
 

leorob88

Member
Joined
Dec 31, 2020
Messages
23
Programming Experience
1-3
I added an image at the beginning of my thread. I repeat it also here: basically the second pic you see (the pink lines) should blink above the map on the left, as you see in the 3rd pic. It blinks, that's just fine. Problem is, for now, it doesn't blink like that, instead it blinks pic1/pic2 and repeat. At the beginning instead, when i got transparent overlaps, it blinked exactly like in the pic3, but yeah, overlapped region became transparent as well.

I tried removing those last 2 lines (of course, didn't think about that), but still nothing changes (for reasons, the result is identical).
I know region has those methods but as i know/understand (tell me if i'm wrong), region has nothing to do with graphics.fill: in fact, the reason why i use region is basically because i need to draw something over a picture leaving transparent all the rest, because i knew if i used graphics it would have just turned the rest default color without transparence.
Basically i also tried methods, instead of those 2 marked rows above (the ones suggested by you), i didn't use the graphicspath and instead i used cyclically:

evidenziapunti.region.complement(punto); // also i tried methods union and intersect

what i got was the region was the whole picturebox for reasons i don't know. the main structure for defining the region to draw is always this, i just try to do minimal changes with those specific rows that define what to do (map.addrectangle, region.complement, graphics.fill, and such). The idea in fact is simple, you have a pictrure and you just have to draw multiple rectangles on it leaving transparent the rest of the picture, and the rectangles are checked and added cyclically to the region during the paint event. It should work and be very simple as i see it...
 

Attachments

  • Immagine.png
    Immagine.png
    11.5 KB · Views: 6
Last edited:

JohnH

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
1,265
Location
Norway
Programming Experience
10+
I recommend you post an example that we can run to see where the problem is. All that is needed is a picturebox with an image and the code to draw one blinking rectangle like you do it.
 
Top Bottom