Keeping a PictureBox centered inside a container - c#

I am designing a simple picture viewer with ability to do some basic image processing. At the moment I have the problem of keeping the PictureBox centered inside a TabPage all the time as well as keeping the picturebox width and size same as the picture its showing. So far I had no success.
I have the following code that I call in form constructor to position it in center. it works the first time to center the picturebox:
private void SetPictureBoxOriginalSizeAndLocation(bool makeImageNull = false, DockStyle dockStyle = DockStyle.None)
{
if (makeImageNull) picBoxView.Image = null;
picBoxView.Dock = dockStyle;
var xPoint = tabImageView.Location.X + ((splitContainer.Panel2.Width / 2) / 2);
var yPoint = tabImageView.Location.Y;
var width = tabImageView.Width / 2;
var height = (tabImageView.Height / 2) - toolStripImageView.Height;
if (picBoxView.Image == null) return;
//Resize image according to width
picBoxView.Image = ImageMethods.ResizeImage(picBoxView.Image.Tag.ToString(), width, height, false);
picBoxView.Location = new Point(xPoint, yPoint);
picBoxView.Width = width;
picBoxView.Height = height;
}
But it does not resize the picturebox to its image (you can see the black part that is back color for the picturebox control):
The problem is getting worse as soon as I resize the form, the picturebox position will goes to top:
I call the code above in form's resize event as well, no idea why it works when application starts. Would be nice if someone can tell me what properties I should take care of to achieve a nicely centered picturebox which always is as big as its image.

It's pretty easy if you just set the Anchor style to none:
picBoxView = new PictureBox();
picBoxView.SizeMode = PictureBoxSizeMode.AutoSize;
picBoxView.Anchor = AnchorStyles.None;
tabImageView.Controls.Add(picBoxView);
CenterPictureBox(picBoxView, myImage);
Then just center the PictureBox initially whenever you change the image of the PictureBox:
private void CenterPictureBox(PictureBox picBox, Bitmap picImage) {
picBox.Image = picImage;
picBox.Location = new Point((picBox.Parent.ClientSize.Width / 2) - (picImage.Width / 2),
(picBox.Parent.ClientSize.Height / 2) - (picImage.Height / 2));
picBox.Refresh();
}
Having the Anchor = None will center the PictureBox control for you whenever the parent container gets resized because it "isn't" anchored to the default Left and Top locations.

Givien a Form with TabControl, which has Dock set to Fill, below will keep your PictureBox in the centre. It also sets PictureBox size to Bitmap size:
public partial class Form1 : Form
{
Bitmap b = new Bitmap(320, 200);
public Form1()
{
InitializeComponent();
CenterTheBox();
}
private void Form1_Resize(object sender, EventArgs e)
{
CenterTheBox();
}
void CenterTheBox()
{
pictureBox1.Size = b.Size;
var left = (tabPage1.ClientRectangle.Width - pictureBox1.ClientRectangle.Width) / 2;
var top = (tabPage1.ClientRectangle.Height - pictureBox1.ClientRectangle.Height) / 2;
pictureBox1.Location = new Point(tabPage1.ClientRectangle.Location.X + left, tabPage1.ClientRectangle.Location.Y + top);
}
}

I believe your problem lies here
var xPoint = tabImageView.Location.X + ((splitContainer.Panel2.Width / 2) / 2);
var yPoint = tabImageView.Location.Y;
var width = tabImageView.Width / 2;
var height = (tabImageView.Height / 2) - toolStripImageView.Height;
ypoint is alwways set to tabImageView Y, althought it should be set to
tabImageView.Location.Y + (tabImageView.Size.Height - picBoxView.Size.Height)/2
should be almost the same with xPoint
tabImageView.Location.X + (tabImageView.Size.Width - picBoxView.Size.Width)/2
and
width = picBoxView.Image.Width;
height = picBoxView.Image.Height;

Related

How to scroll an zoomed image C#

I have a picturebox and i can zoom it.
When i zoom the picturebox i need to scroll left or right the image.
Can you tell me why when i zoom the image the left side is fixed and i can't scroll on left?
I have activated the AutoScroll on the main panel, but i can scroll only to right, but my image is centered and i need to scoll also to left.
What i want is like when you zoom and scroll an image inside a Photo app in Win 10. But i'm using the scoll bar and not the mouse pointer.
The structure is like in the next image, in red the main panel, and i green the picturebox.
private void image_Scroll(object sender, EventArgs e)
{
int pbWidth = pbImg.Image.Width + (pbImg.Image.Width * ztb.Value / 100);
int pbHeight = pbImg.Image.Height + (pbImg.Image.Height * ztb.Value / 100);
int mpWidth = mainPanel.Width:
int mpHeight = mainPanel.Height;
int pbX = (mpWidth - pbWidth) / 2;
int pbY = (mpHeight - pbHeight) / 2;
pbImg.Size = new Size(pbWidth, pbHeight);
Point p = new Point(pbX, pbY);
pictureBox.Location = p;
}

How do I get width and heigth of picturebox image coming from ImageLocation?

I'm trying to expand my form depending on the resolution of the selected image on the picturebox. But it seems like the picturebox size is not changing when I change the image... any help?
pictureBox1.ImageLocation = reader["imagem"].ToString();
pictureBox1.Height = pictureBox1.Image.Height;
pictureBox1.Width = pictureBox1.Image.Width;
/*mw and mh are the main width and main heigth,
i used this in case the user selects another
image, then the window returns to it's original
size before changing again.*/
this.Height = mh;
this.Width = mw;
this.Height += pictureBox1.Image.Height;
this.Width = pictureBox1.Image.Width + 16;
if (this.Width < mw)
{
this.Width = mw;
}
this.CenterToParent();
This is only the part of the code which I need a fix. The rest is all right and the picturebox is showing the image I select, but it's not changing sizes.
Oh I just figured it out guys, I changed
This part:
pictureBox1.ImageLocation = reader["imagem"].ToString();
To this:
pictureBox1.Image = Image.FromFile(reader["imagem"].ToString());

Form position on lower right corner of the screen

I am using c# WinForm to develop a sman notification app. I would like to place the main form on the lower right corner of the screen working area.
In case of multiple screens, there is a way to find the rightmost screen where to place the app, or at least remember the last used screen and palce the form on its lower right corner?
I don't currently have multiple displays to check, but it should be something like
public partial class LowerRightForm : Form
{
public LowerRightForm()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
PlaceLowerRight();
base.OnLoad(e);
}
private void PlaceLowerRight()
{
//Determine "rightmost" screen
Screen rightmost = Screen.AllScreens[0];
foreach (Screen screen in Screen.AllScreens)
{
if (screen.WorkingArea.Right > rightmost.WorkingArea.Right)
rightmost = screen;
}
this.Left = rightmost.WorkingArea.Right - this.Width;
this.Top = rightmost.WorkingArea.Bottom - this.Height;
}
}
Override the Form Onload and set the new location :
protected override void OnLoad(EventArgs e)
{
var screen = Screen.FromPoint(this.Location);
this.Location = new Point(screen.WorkingArea.Right - this.Width, screen.WorkingArea.Bottom - this.Height);
base.OnLoad(e);
}
//Get screen resolution
Rectangle res = Screen.PrimaryScreen.Bounds;
// Calculate location (etc. 1366 Width - form size...)
this.Location = new Point(res.Width - Size.Width, res.Height - Size.Height);
This following code should work :)
var rec = Screen.PrimaryScreen.WorkingArea;
int margain = 10;
this.Location = new Point(rec.Width - (this.Width + margain), rec.Height - (this.Height + margain));
int x = Screen.PrimaryScreen.WorkingArea.Right - this.Width;
int y = Screen.PrimaryScreen.WorkingArea.Bottom - this.Height;
// Add this for the real edge of the screen:
x = 0; // for Left Border or Get the screen Dimension to set it on the Right
this.Location = new Point(x, y);

How can I make a button take up its entire containing form?

I've made a floating button. I want it to take up the whole of the it's containing form but the below code has a margin between the right of the button and the right of the form.
public FloatButton()
{
InitializeComponents();
int width = (int)((double)Screen.PrimaryScreen.Bounds.Width / 20);
int height = (int)((double)Screen.PrimaryScreen.Bounds.Height / 20);
this.WindowState = FormWindowState.Normal;
FormBorderStyle = FormBorderStyle.None;
int x_pos = Screen.PrimaryScreen.Bounds.Width - width;
int y_pos = Screen.PrimaryScreen.Bounds.Height / 2 - height / 2;
this.Location = new Point(x_pos,y_pos);
this.Height = height;
this.Width = width;
this.button.Width = width;
this.button.Height = height;
}
EDIT: It's about 40 pixels and it doesn't change if I make the button text longer (the text wraps)
Does docking work for you?
this.button.Dock = System.Windows.Forms.DockStyle.Fill;
Just setting Dock to Fill should make the button fill up its parent's entire area.

Is it possible to rotate a button control in WinForms?

Is it possible to rotate a button or any control at a particular angle in WinForms? If so, how?
If you really want to (I have no idea why one would..*) you could try to use a Button subclass, maybe like that:
public partial class TurnButton : Button
{
public TurnButton()
{
InitializeComponent();
}
int angle = 0; // current rotation
Point oMid; // original center
protected override void OnLayout(LayoutEventArgs levent)
{
base.OnLayout(levent);
if (oMid == Point.Empty) oMid = new Point(Left + Width / 2, Top + Height / 2);
}
protected override void OnPaint(PaintEventArgs pe)
{
int mx = this.Size.Width / 2;
int my = this.Size.Height / 2;
SizeF size = pe.Graphics.MeasureString(Text, Font);
string t_ = Text;
Text = "";
base.OnPaint(pe);
if (!this.DesignMode)
{
Text = t_; pe.Graphics.TranslateTransform(mx, my);
pe.Graphics.RotateTransform(angle);
pe.Graphics.TranslateTransform(-mx, -my);
pe.Graphics.DrawString(Text, Font, SystemBrushes.ControlText,
mx - (int)size.Width / 2, my - (int)size.Height / 2);
}
}
protected override void OnClick(EventArgs e)
{
this.Size = new Size(Height, Width);
this.Location = new Point(oMid.X - Width / 2, oMid.Y - Height / 2);
angle = (angle + 90) % 360;
Text = angle + "°";
base.OnClick(e);
}
}
(* I have no idea why I wrote that, either ;-)
You can't rotate controls. That's simply not supported by the native API controls that WinForms uses.
And one might wonder why it even should be supported. What could you possibly be trying to do that you'd need to rotate a button control? It would be much easier to draw it in a different place with a different shape in the first place, rather than trying to rotate an existing control. (Do note that you can also resize and reposition a control at run-time, if that would fit your needs. Investigate the Size and Location properties.)
The only workaround is to draw the control's image to a bitmap, hide the control, and draw the bitmap onto the form in the location you want it to appear. Of course, that won't result in a control that the user can interact with. They won't be able to click an image of a button, because it's not a real button. If that's acceptable to you, you should probably be using an image in the first place, rather than a button.
This is similar to the question asked here:
Rotating a .NET panel in Windows Forms
The quick summary of answers from that question is that while it may be possible to do it, it would be very, very complicated.
A possible workaround in some cases would be this:
Use a tabControl , and resize it so you only have the button left. Set the allignment to left/right, and you have your button rotated 90/270 degrees.
public class VerticalButton : Button
{
public string VirticalText { get; set; }
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
StringFormat stringFormat = new StringFormat();
stringFormat.FormatFlags = StringFormatFlags.DirectionVertical;
SolidBrush solidBrush = new SolidBrush(this.ForeColor);
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;
pe.Graphics.DrawString(VirticalText, this.Font, solidBrush,
new Rectangle(0, 0, Width, Height), stringFormat);
}
}

Categories