How can I keep center align images added dynamically to a panel? - c#

I have a WinForms empty panel, and I'm adding images dynamically to this panel.
To center the first image added, I just:
Get the width (WP) of the panel and divide by 2;
Get the width (WI) of the image and divide by 2;
WP - WI = Left position of image X;
But I can't figure out some dinamically way to set this position when I have more than one image. Is there a way to calculate this X ? Am I right about this? Is there a easier way?
Thanks.

Well if you have only one row, some where you can have a collection of Image objects, say
List<Image> images.
And method
void PositionImages()
{
int totalWidth = images.Sum(img=>img.Width);
int startX = (panel.Width - totalWidth)/2;
}
Should work to you, but you will need to check it. For example I suppose here that tolalWidth of all images in collection is always less then panel.Width.

Related

How to determine if control is outside of Form?

I am trying to determine if a dynamically added control is outside of the form.
At first, I thought it might be possible to calculate it by getting the height of the form, and location of the dynamically added control.
But I noticed that the Control.Location and Form.Height have "nothing" in common.
I don't think I really understand what the correlation is between Height and Location.
For example:
I thought that if your form has a height of 500, and I put the control at the bottom of the form, it should give the Location: X, 500 (X is width, not relevant here). But this is not correct, it shows me for example: X, 465. Am I missing something?
So I need to be able to recognize if the control is outside of the form, even if it's just one pixel.
I've found several similar questions here on SO, yet this does not really give me the answer that I need, unfortunately.
So, is there any way to do this? Is it possible to calculate it?
The Height of the form also includes the height of the title bar and borders.
You can use the ClientSize of the form:
From the documentation on MSDN:
The size of the client area of the form is the size of the form excluding the borders and the title bar. The client area of a form is the area within a form where controls can be placed. You can use this property to get the proper dimensions when performing graphics operations or when sizing and positioning controls on the form. To get the size of the entire form, use the Size property or use the individual properties Height and Width.
The position of the control is relative to its container, so (0,0) is the left upper corner inside the form.
I know this is an older thread, but you can try using this method:
public static bool IsOutofBounds(Form form, Control control)
{
int controlEnd_X = control.Location.X + control.ClientSize.Width;
int controlEnd_Y = control.Location.Y + control.ClientSize.Height;
if (form.ClientSize.Width < controlEnd_X || form.ClientSize.Height < controlEnd_Y)
{
return true;
}
else
{
return false;
}
}
It works for checking whether a control is out of bounds of its parent form.
You could use this code to check if controls is inside form:
var Inside = frm.ClientRectange.Intersect(ctrl.Bounds) == ctrl.Bounds;
the top left corner of a form is (0,0) lower right corner is (formHeight, fromWidth).
to check this place two text boxes on a form and write this code in the mouse move event to see how x and y change.
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
textBox1.Text = e.X.ToString();
textBox2.Text = e.Y.ToString();
}
Note that there is an difference between the number returned from the edge of the form and the size chosen by you. In my 500*500 form it is actually 460*483. the difference is always the same for any border style and any resolution.
To place a control on your form use the location structure in the form or use the top and left properties for the control; top = x, left = y.
Remember your offset from the actual height and width you measured and the dimension of the control.
To add a button with the following dimensions 80*30 in the bottom right corner I would right something like this:
button1.Location = new System.Drawing.Point(402, 430);
bottom left corner:
button1.Location = new System.Drawing.Point(0, 430);

Add images on chart control

I'm not sure if I titled the question correctly so it would be better if I explained what I'm trying to do. I want to add some images on chart control and
around their to draw graphics.
I want to display the layout of the sensors on the coordinate plane defined by coordinates, while noting the location of geographic objects (forest, river, etc.). These objects will be images which I want to add to the chart/
How can I do it? It is possible?
If you show us an example we may be able to help to find the best way.
There are several options.:
You can place image controls like PictureBox or Panel on the Chart by adding them to the chart's Controls collection
You can draw them in the Pre- or PostPaint event
You can assemble a BackImage that contains all the Images you want to place around the chart.
You can add ImageAnnotations to the chart. (Recommended)
The latter obviously is the one that is best integrated.
Here is an example:
We start by adding the images we want to use to the Chart's Images collection:
List<string> imgFiles = new List<string>()
{ yourImageFileName1, ...};
for (int i = 0; i < imgFiles.Count; i++)
{
Image img = Bitmap.FromFile(imgFiles[i]);
chart1.Images.Add(new NamedImage("Image" + i, img));
}
Note the NamedImage class used here. It allows you to refer to the images by a string; pick better names! Maybe Path.GetFileNameWithoutExtension(imgFiles[i]) - Also note that you must not Dispose of the Images or else they will disappear!
Next make make a little room at the right side of the chart by reducing the ChartArea's size:
ChartArea ca = chart1.ChartAreas[0];
ca.Position = new ElementPosition(5,5,70,90);
Note the values are percentages of the Chart's ClientSize, so they will grow and shrink when resizing the Chart!
Finally we can add them all. You will want to add them at specific positions. I add them at some space to the right and also make them moveable:
foreach (NamedImage img in chart1.Images)
{
ImageAnnotation ia = new ImageAnnotation();
ia.Image = img.Name;
ia.AllowMoving = true;
ia.X = 77;
ia.Y = 15 * chart1.Images.IndexOf(img) + 5;
chart1.Annotations.Add(ia);
}
Now you should see the Annotions. And if you add this event:
private void chart1_AnnotationPositionChanging(object sender,
AnnotationPositionChangingEventArgs e)
{
testLabel.Text = e.Annotation.X + " " + e.Annotation.Y;
}
..you will see just what the numbers for the best position are. Eventually you will not keep them moveable, of course..
Note the the Annotations' position is also in percentages, so they will move along nicely, when the chart get resized! You may also scale the Images by setting the Width and Height; this is a little tricky, as it will also be in percent (and not as the docs falsely state in pixels). You would probably want to loop over the ImageAnnotations and rescale them in the Resize event..: ia.Height = ia.Width * chart1.Width / chart1.Height;
Also note that there are other ways to position annotations, like anchored to datapoints, but this seem the best for a static adornment.

Fill width of panel with rectangles(variable size)

I'm making a sorting algorithm vizualizer(Like Sound of Sorting without the Sound) But i stumbled upon a problem, and i can't seem to figure it out. I need to layout rectangles over the width of a panel(variable amount).
Image of the bars:
But when i get more bars, sometimes i will get a blank space because it won't fit:
How can i make it that some rectangles are a bit bigger than some others to make it fit? The way i calculate the width right now is like this:
barWidth = draw.Width / amount; //draw is the panel where i draw the rectangles on
Any help will be greatly appreciated!
I guess this is a rounding issue so I think you need to do some calulations:
totalBarWidth = sum of barWidths
blankSpace = draw.Width - totalBarWidth
numberOfBarsPerBlankSpacePixel = amount / blank space
Loop over the bars and add a pixel to the width of every numberOfBarsPerBlankSpacePixel bars.
Also don't forget to add the pixels to the x-axis location of the following bars.

Canvas has Width of 0 after adding children. How to cause canvas to recalculate width?

I'm creating a custom canvas which has dynamically added shapes (lines) which are added as children. Unfortunately, after adding the children, the canvas has a width of 0, which is not expected.
Ideally, the canvas should update its width by using its children's dimensions.
How can I modify my canvas to account for the dimensions of its children, and then update its width?
As I said, I changed the shapes on the canvas dynamically. I do this every time one of its dependency properties is changed using a callback function.
Generally, this is what that callback function looks like:
This is not my algorithm, but it should demonstrate the point.
public void UpdateLines()
{
for(int i = 0; i < NUM_BARS; i++)
{
Line bar = new Line();
bar.Stroke = Brushes.Black;
bar.StrokeThickness = 4;
bar.X1 = 0;
bar.X2 = ActualWidth;
bar.Y1 = i * (bar.StrokeThickness + 2);
bar.Y1 = bar.Y2;
this.Children.Add(bar);
}
//[Inserted here]
}
The next thing I noticed is that I could add a line with a large length, and that line would appear, but the canvas width would still remain 0.
At the "Inserted Here" mark, I put this line of code to test:
Children.Add(new Line() { Stroke=Brushes.Black,
StrokeThickness = 4, X1 = 0, X2 = 200, Y1 = 10, Y2 = 10 });
So, why the canvas width is not updating properly? I need to use it for calculating the size of my lines.
Your help is greatly appreciated. Thanks.
Please refer to the Panels Overview page on MSDN for further help with WPF Panels, but in short, the Canvas Panel does not resize itself when child items are added (or at any time). From the linked page:
Canvas is not affected by the size of its children. As a result, it is possible for a child element to overdraw other elements outside the bounding rectangle of the parent Canvas.
Therefore, you will either need to manually update the size of the Canvas, or use a different type of layout Panel that does resize itself when child items are added, although the Canvas is the only Panel that enables users to place child controls at absolute positions within it.
Again, from the linked page:
Canvas provides the most flexible layout support of any Panel. Height and Width properties are used to define the area of the canvas, and elements inside are assigned absolute coordinates relative to the area of the parent Canvas. Four attached properties, Canvas.Left, Canvas.Top, Canvas.Right and Canvas.Bottom, allow fine control of object placement within a Canvas, allowing the developer to position and arrange elements precisely on the screen.

WinForms: ImageList for ListView with different image sizes

I have a ListView with View property set to LargeIcon. And I have an ImageList as image source for ListView.
What I want is to display both vertically and horizontally oriented images in ListView but ImageList have only a single property ImageSize for all images in its collection so for example if I set that property to 150x100 and add a vertical image (100x150) to collection - ListView automatically stretches it to 150x100.
So as I understand I need some ImageList, in which every image is stored with its original size. Any thoughts about how to do that?
Thanks in advance.
I have had this problem myself, Here is what I did, I hope it will help you as well, first determine the biggest image size you would use ( for example 200x200) then use Png or Gif images (all 200x200) with transparent backgrounds.
have a look at these two images i have created as an example.
but I make it like this to avoid stretching:
To keep from stretching you can use cross-multiplication.
Image Width Desired Width
--------------- = ---------------
Image Height New Height
or
Image Width New Width
--------------- = ---------------
Image Height Desired Height
In code it looks something like this
int height = img.Width*newWidth/image.Height;
or
int height = img.Width/image.Height*newWidth;
and
int width = img.Height*newHeight/image.Width;
or
int width = img.Height/image.Width*newHeight;
Then when creating your new bitmap you can draw a scaled image on the new bitmap using the desired size and the derived size.

Categories

Resources