Strange Behavior with Pictureboxes - c#

I am experiencing strange behavior with PictureBoxes and have narrowed down a test case.
I have four PictureBoxes on my test form. Two have a background color set ... one red, one blue:
If I add the following code, the red Picturebox correctly parents itself to the upper Picturebox:
this.redPictureBox.Parent = this.pictureBox1;
this.redPictureBox.Location = this.pictureBox1.Location;
this.redPictureBox.Height = this.pictureBox1.Height;
this.redPictureBox.Width = this.pictureBox1.Width;
This works as expected:
However, if I add code to do the exact same thing with the blue PictureBox, nothing happens. In fact, it appears that the second PictureBox from the top disappears altogether:
this.bluePictureBox.Parent = this.pictureBox2;
this.bluePictureBox.Location = this.pictureBox2.Location;
this.bluePictureBox.Height = this.pictureBox2.Height;
this.bluePictureBox.Width = this.pictureBox2.Width;
Why is this behavior occuring? I must be missing something obvious but the code between the two is identical ... so why the different behavior?

I suspect this is the problem:
this.bluePictureBox.Location = this.pictureBox2.Location;
You're setting the location of the blue picture box within picture box 2 to be the location of picture box 2 relative to the container. I suspect you want:
this.bluePictureBox.Location = new Point(0, 0);
The only reason this wasn't much of an issue for the red picture box is that picture box 1 is near the top of the screen. Even so, you can see that it's not the full height/width that it was, and it's not at the top-left of picture box 1.

Related

Visual C# creating list of items

I need to make an application that shows codes that update from time to time.
Now I got the back-end part covered but I am completely new to the front end part.
I'd basicly like it took look something like this:
Now the idea is that I'll have a List that holds items that should be converted to elements in the below visual list.. The logo is something I staticly added and that is anchored to the left top corner, I'd like to create the rest of the elemnents dynamically (I have a timed event loop to check if the list has changed, etc)
So I made the following method as a starting point:
private void createOTPEntry()
{
Rectangle entry = new Rectangle();
entry.Name = "entry1";
entry.Stroke = new SolidColorBrush(Color.FromRgb(0, 111, 0));
entry.Fill = new SolidColorBrush(Color.FromRgb(243, 86, 13));
entry.Height = 65;
entry.Width = 497;
Thickness margin = entry.Margin;
margin.Left = 10;
margin.Top = 83;
entry.Margin = margin;
entry.BringIntoView();
}
Now this isn't relative yet to the logo or anything.. But it's supposed to atleast be a white rectangle with an orange border.. And it's not showing. I tried to find if my rectangle object has like a "show" or "draw" method but it doesn't.. And I'm still miles away from what I really want..
So the logic of what I want:
Loop that goes over list elements and draws the visual list elements, probably a Rectangle containing 2 TextBoxes or Labels (one of the labels will change)
These elements will be added to another Container? that has a scrollbar in case there are to many elements.
I'd like some help of possible on what control do I choose to add the elements to? (the container witht he scrollbar?). How exactly do I show my rectangle? Is there an easy way to make them kinda automaticly space when I add them to the "parent control" (the scrollable container).
Thanks in advance for giving me a jump start!

Make Picture boxes transparent, each overlapping the other with a corner?

TL;DR: Look at the picture below
So I'm trying to make a little picture, and I and people around me are kinda out of ideas.
I have a table (the sitting+eating one) in the middle (seen from above), and people sitting around it. Those people are round, as isthe table.
Every person has their own picturebox, I just use one picture, rotate it, and set it as image in the next box.
Thep roblem now is: The PictureBoxes of people on corners overlap the table with empty corner, in the image there is transparency there. It should show the table below it, but instead it shows the background of the Form :(
Edit: All backgrounds are set to transparent, the Form has the marble as background and white ("Window") as background colour.
I put one person in the back and one in the front, so it's easy to see:
Edit 2 (same as ocmment):
In the last two days I read this question about 10 times, and not one that described this exact problem has had an actual answer. When trying to push one of those, I was told I should post a new question.
Example: How to make picturebox transparent?
Transparency in winforms is kind of misleading, since it's not really transparency.
Winforms controls mimic transparency by painting the part of their parent control they would hide instead of their own background.
However, they will not paint the other controls that might be partially covered by them.
This is the reason your top most picture boxes hides your big picture box.
You can overcome this by creating a custom control that inherits from PictureBox and override its OnPaintBackground method (taken, with slight adjustments, from this code project article):
protected override void OnPaintBackground(PaintEventArgs e)
{
base.OnPaintBackground(e);
Graphics g = e.Graphics;
if (this.Parent != null)
{
var index = Parent.Controls.GetChildIndex(this);
for (var i = Parent.Controls.Count - 1; i > index; i--)
{
var c = Parent.Controls[i];
if (c.Bounds.IntersectsWith(Bounds) && c.Visible)
{
using (var bmp = new Bitmap(c.Width, c.Height, g))
{
c.DrawToBitmap(bmp, c.ClientRectangle);
g.TranslateTransform(c.Left - Left, c.Top - Top);
g.DrawImageUnscaled(bmp, Point.Empty);
g.TranslateTransform(Left - c.Left, Top - c.Top);
}
}
}
}
}
Microsoft have published a Knowledge base article to solve this problem a long time ago, however it's a bit out-dated and it's code sample is in VB.Net.
Another option is to paint the images yourself, without picture boxes to hold them, by using Graphics.DrawImage method.
The best place to do it is probably in the OnPaint method of the form.

How to make picture box background transparent in c#

Suppose i have a big Picture box that its image is like a grid.. and 5 other small picture boxes that have different images that i want to place them in the big one and their location is always changeable(by changing their location randomly and sometimes they rotate ).
However , the problem is that these picture boxes have the background white and not transparent everytime i compiled my code as i changed their property back color to transparent
i tried this general code (that i found it alot as a solution for my problem):
overImage.Parent = backImage;
overImage.BackColor = Color.Transparent;
overImage.Location = thePointRelativeToTheBackImage;
and tried this:
innerPictureBox.SendToBack();
innerPictureBox.Parent = outerPictureBox;
but they work so badd and they only work for one time...what to do if i want to make them always transparent with not changing their desired location where i want to put them

Coloring area of an image on mouse click over picturebox

I would like to be able to fill any given area of an image with a given color, much like you can use paint to fill a rectangle, circle or any other shape delimited by a color.
To make this simpler I already have made the picture box source image to have the same size as the picture box itself, which should make things a bit easier.
How can I do this given that I have a picture box with an image and an already defined color and the user only has to click over the picture box to fill in any area with such color.
void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
// The color to be used
Color color = Color.Red;
// Image has same dimensions as picturebox to make things easier
Image img = pictureBox1.Image;
// Where it was clicked.
Point clickCoords = new Point(e.X, e.Y);
// Coloring that area clicked much like Paint does. How?
...
// After coloring show the result in the picture box again
pictureBox1.Image = img;
}
Thanks.
EDIT: Example of my desired behavior.
To make my goal obvious, let me add this small example.
You know MS Paint right?
You selected the pencil tool and start doing anything on the canvas, doesn't matter form or shape or even if the points your are doing with the pencil are connected or not.
Now you select the bucket tool and start clicking on the canvas. What will it do? Fill in the selected area according to the color you clicked over and how far she goes without changing with the color you have selected on the color pallet.
This is the behavior I want to emulate on my picture box mouse click event.
What you are looking for is a flood-fill algorithm. This should do the trick just fine.
The algorithm recursively searched for neighboring uncolored pixels, until it hits a wall.
You can use the code from here:
// Load the image (probably from your stream)
Image image = Image.FromFile( imagePath );
using (Graphics g = Graphics.FromImage(image))
{
Color customColor = Color.FromArgb(50, Color.Gray);
SolidBrush shadowBrush = new SolidBrush(customColor);
g.FillRectangles(shadowBrush, new RectangleF[] { rectFToFill });
}
image.Save( imageNewPath );
, but there is a one thing you missed - a rectFToFill, which you should define according your click event. There are a lot of strategies you can use, I suggest you to handle a Drag event or something like that, save the event start point and end point, after that define the rectangular you must fill:
You should examine the event points and after that create the Rectangle(F) structure using some of its constructors.
The Graphics class has a dozen methods you can use to draw some shapes or lines on your Image.

C# Screenshot of Control is white

My question is related to this one: How to get a screen capture of a .Net WinForms control programmatically?
I want to take a screenshot of a System.Windows.Forms.Control in C#. I'm using the DrawToBitmap method suggested in the question linked above and that works most of the time. However there are a few problems.
Problem 1:
I have two tabpages, let's call them A and B. The Control I want to take a screenshot of is in tabpage B. I want to take the screenshot when a button in tabpage A is pressed. This works most of the time, except when tabpage B hasn't been accessed yet: then the screenshot is just white. If I first access tabpage B, then go back to tabpage A and click the button to take the screenshot then it works fine. I'm guessing this is because of some loading or building of the control in the tab that hasn't been done yet, but I'm not sure what exactly (or it could be something else entirely). I've been trying to force that loading or building using ResumeLayout, PerformLayout, Show, Update, Invalidate but that doesn't work.
EDIT: Managed to solve this by using DrawToBitmap on the containing tabpage control instead of the Control itself and doing a Show on that tabpage.
Problem 2:
When I take a screenshot of a certain custom Control (a subclass of UserControl) there is a small rectangular white area in the screenshot (where there shouldn't be one obviously). The rectangular area isn't on one particular part of the control like a button or textbox so I'm not sure what's causing this. On other custom Controls (also subclasses of UserControl) it works fine, so that couldn't be the problem itself.
EDIT: Solved it, there was an empty control there that was being drawn on top of it. Setting Visible to false for that control solved it.
You can do with this code, the rest of the work and finding the correct coordinates is for the reader to do the homework.
int screenWidth = Screen.GetBounds(new Point(0, 0)).Width;
int screenHeight = Screen.GetBounds(new Point(0, 0)).Height;
Bitmap bmpScreenShot = new Bitmap(screenWidth, screenHeight);
Graphics gfx = Graphics.FromImage((Image)bmpScreenShot);
gfx.CopyFromScreen(0, 0, 0, 0, new Size(screenWidth, screenHeight));
bmpScreenShot.Save("test.jpg", ImageFormat.Jpeg);
For problem 1: If "If I first access tabpage B, then go back to tabpage A and click the button to take the screenshot then it works fine" then add in formloadevent imitating of that actions:
tabControl.SelectedIndex = IndexOfTabB;
tabControl.SelectedIndex = IndexOfTabA;
That is trick but it will work.
For problem 2: Can you compare sizes of your control and screenshot of It and give results to us? If Control.Width is not equal wirdth of bitmap screen then It is a real problem.

Categories

Resources