Clear image on picturebox - c#

How can I clear draw image on picturebox?
The following doesn't help me:
pictbox.Image = null;
pictbox.Invalidate();
Please help.
EDIT
private void pictbox_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
vl.Draw(g, ref tran.realListForInsert);
}
public void Draw(Graphics g, ref List<double> arr)
{
g.DrawRectangle(new Pen(Brushes.Red, 3), nodeArr[Convert.ToInt32(templstName)].pict.Location.X, nodeArr[Convert.ToInt32(templstName)].pict.Location.Y, 25, 25);
g.DrawRectangle(new Pen(Brushes.Green, 3), nodeArr[Convert.ToInt32(templstArgName)].pict.Location.X, nodeArr[Convert.ToInt32(templstArgName)].pict.Location.Y, 25, 25);
nodeArr[Convert.ToInt32(templstName)].text.Text = arr[Convert.ToInt32(templstArgName)].ToString();
arr[Convert.ToInt32(templstName)] = arr[Convert.ToInt32(templstArgName)];
}

Setting the Image property to null will work just fine. It will clear whatever image is currently displayed in the picture box. Make sure that you've written the code exactly like this:
picBox.Image = null;

As others have said, setting the Image property to null should work.
If it doesn't, it might mean that you used the InitialImage property to display your image. If that's indeed the case, try setting that property to null instead:
pictBox.InitialImage = null;

if (pictureBox1.Image != null)
{
pictureBox1.Image.Dispose();
pictureBox1.Image = null;
}

You need the following:
pictbox.Image = null;
pictbox.update();

private void ClearBtn_Click(object sender, EventArgs e)
{
Studentpicture.Image = null;
}

I assume you want to clear the Images drawn via PictureBox.
This you would be achieved via a Bitmap object and using Graphics object. you might be doing something like
Graphics graphic = Graphics.FromImage(pictbox.Image);
graphic.Clear(Color.Red) //Color to fill the background and reset the box
Is this what you were looking out?
EDIT
Since you are using the paint method this would cause it to be redrawn every time, I would suggest you to set a flag at the formlevel indicating whether it should or not paint the Picturebox
private bool _shouldDraw = true;
public bool ShouldDraw
{
get { return _shouldDraw; }
set { _shouldDraw = value; }
}
In your paint just use
if(ShouldDraw)
//do your stuff
When you click the button set this property to false and you should be fine.

For the Sake of Understanding:
Depending on how you're approaching your objective(s), keep in mind that the developer is responsible to Dispose everything that is no longer being used or necessary.
This means: Everything you've created along with your pictureBox (i.e: Graphics, List; etc) shall be disposed whenever it is no longer necessary.
For Instance:
Let's say you have a Image File Loaded into your PictureBox, and you wish to somehow Delete that file.
If you don't unload the Image File from PictureBox correctly; you won't be able to delete the file, as this will likely throw an Exception saying that the file is being used.
Therefore you'd be required to do something like:
pic_PhotoDisplay.Image.Dispose();
pic_PhotoDisplay.Image = null;
pic_PhotoDisplay.ImageLocation = null;
// Required if you've drawn something in the PictureBox. Just Don't forget to Dispose Graphic.
pic_PhotoDisplay.Update();
// Depending on your approach; Dispose the Graphics with Something Like:
gfx = null;
gfx.Clear();
gfx.Dispose();
Hope this helps you out.

I've had a stubborn image too, that wouldn't go away
by setting the Image and InitialImage to null.
To remove the image from the pictureBox for good, I had to use the code below,
by calling Application.DoEvents() repeatedly:
Application.DoEvents();
if (_pictureBox.Image != null)
_pictureBox.Image.Dispose();
_pictureBox.Image = null;
Application.DoEvents();
if (_pictureBox.InitialImage != null)
_pictureBox.InitialImage.Dispose();
_pictureBox.InitialImage = null;
_pictureBox.Update();
Application.DoEvents();
_pictureBox.Refresh();

I had to add a Refresh() statement after the Image = null to make things work.

I used this method to clear the image from picturebox. It may help some one
private void btnClear1_Click(object sender, EventArgs e)
{
img1.ImageLocation = null;
}

Its so simple!
You can go with your button click event,
I used it with a button property Name: "btnClearImage"
// Note 1a:
// after clearing the picture box
// you can also disable clear button
// by inserting follwoing one line of code:
btnClearImage.Enabled = false
// Note 1b:
// you should set your button Enabled property
// to "False"
// after that you will need to Insert
// the following line to concerned event or button
// that load your image into picturebox1
// code line is as follows:
btnClearImage.Enabled = true;

You should try. When you clear your Graphics you must choose color. SystemColors.Control is native color of form
Graphics g = pB.CreateGraphics();
g.Clear(SystemColors.Control);

clear pictureBox in c# winform Application
Simple way to clear pictureBox in c# winform Application

Related

Getting resources Image path from Picturebox [duplicate]

I have a program which has 16 grid tiles using picturebox but only uses 5 images, the rest of the tiles are just a black image.
I would like to be able to tell which image the 'user' clicks on.
I have a method called image_Click(object sender, EventArgs e)
I have an if statement inside this method that states:
if (peckedSquare.BackColor == Color.Black)
{
System.Diagnostics.Debug.WriteLine("Pecked a black square");
return;
}
This sends a String that lets me know when a black square has been clicked.
Is there an easy way to perhaps say:
//pseudo code:
if (peckedSquare.ImageName == pigeon1.png)
{
System.Diagnostics.Debug.WriteLine("Pecked Pigeon number 1");
}
I have googled my query but I have not found any suitable answers.
//EDIT
I have just re-read my code.
I was assigning each picture to a picturebox square using a randomnumber.
I had this random number as a variable, so I can just use that variable to determine which image was clicked.
ie.
if (randomNumber == 1)
{
System.Diagnostics.Debug.WriteLine("Pecked Pigeon number 1");
}
or better than that
pigeonSelected = randomNumber + 1 //as I am using an array to store the images
System.Diagnostics.Debug.WriteLine("Pecked Pigeon Number {0}", pigeonSelected);
As quick & dirty solution I would use Tag property for that, null for black tiles and file path for the others (and it's always available, even if your image comes from resources), something like this:
if (peckedSquare.Tag == null)
{
Debug.WriteLine("Pecked a black square");
}
else
{
switch (Path.GetFileName(peckedSquare.Tag.ToString()))
{
case "pigeon1.png":
break;
}
}
Of course when you create tiles you have to store file path in Tag:
PictureBox tile = new PictureBox();
tile.Image = Image.FromFile(path); // Or another source, of course
tile.Tag = path;
As alternative you may even use Name property for this, each control is named (primary for designer-code integration) but if you create controls at run-time you can set that value to anything you want (not only valid identifiers). Same usage as above just no need to call ToString().
How to Improve?
Please let me say this solution is not very OOP. Even without a big refactoring we can do little bit better. Note that you can store whatever you want in Tag property. A number, a simple string unrelated to file name or even (maybe better) a class or an enum that represents that image (to delegate action to that object). This is a very raw example:
abstract class Tile {
public abstract void Activate();
}
sealed class EmptyTile : Tile {
public virtual void Activate() {
Debug.WriteLine("Pecked a black square");
}
}
sealed class ImageTile : Tile {
public ImageTile(string content) {
_content = content;
}
public virtual void Activate() {
Debug.WriteLine(_content);
}
private string _content;
}
In this way in your click event handler you can do this:
((Tile)peckedTile.Tag).Activate();
No need to check what's inside or to compare with null. No if and no switch, just don't forget to put proper object (ImageTile or BlackTile) when you create tiles.
Use PictureBox.Load(string) method to load images from file. Then the file path will be stored in the
PictureBox.ImageLocation property:
A call to the Load method will overwrite the ImageLocation property, setting ImageLocation to the URL value specified in the method call.
So you can write for example:
if (peckedSquare.ImageLocation.EndsWith("pigeon1.png"))
{
System.Diagnostics.Debug.WriteLine("Pecked Pigeon number 1");
}
I think you could do something like the following:
private List<PictureBox> pictures = null;
string[] ImageNames = new string[]
{
"images\\test_1.jpg",
"images\\test_2.jpg"
};
private void Form1_Load(object sender, EventArgs e)
{
pictures = new List<PictureBox>();
for (var idx = 0; idx < ImageNames.Length; idx++)
{
pictures.Add(new PictureBox());
pictures[idx].Image = new Bitmap(ImageNames[idx]);
pictures[idx].Click += OnClick;
// you'll want to set the offset and everything so it shows at the right place
Controls.Add(pictures[idx]);
}
}
private void OnClick(object sender, EventArgs eventArgs)
{
// you'll definitely want error handling here
var ImageName = ImageNames[pictures.IndexOf((PictureBox) sender)];
}
You can see that in the click method you will be able to get the image name, which is what you are looking for I believe.
As others have said, you can also use the "Tag" property assuming you weren't already using this for some other purpose. The nice thing about tag is you can probably also edit it through the form designer which allows you to lay things out a little more nicely than the automatic layout I used above. Good luck!
You can do something like this using the Tag property like #Adriano suggested:
public Form1()
{
InitializeComponent();
pictureBox1.Click += pictureBox_Click;
pictureBox2.Click += pictureBox_Click;
pictureBox3.Click += pictureBox_Click;
// ...
pictureBox1.Tag = "picture1.png";
pictureBox2.Tag = "picture2.png";
pictureBox3.Tag = "picture3.png";
}
void pictureBox_Click(object sender, EventArgs e)
{
PictureBox pb = sender as PictureBox;
if (pb.BackColor != Color.Black)
Debug.WriteLine(pb.Tag.ToString());
else
Debug.WriteLine("Black image");
}

How do you access the name of the image in a picturebox in Visual Studio using C#

I have a program which has 16 grid tiles using picturebox but only uses 5 images, the rest of the tiles are just a black image.
I would like to be able to tell which image the 'user' clicks on.
I have a method called image_Click(object sender, EventArgs e)
I have an if statement inside this method that states:
if (peckedSquare.BackColor == Color.Black)
{
System.Diagnostics.Debug.WriteLine("Pecked a black square");
return;
}
This sends a String that lets me know when a black square has been clicked.
Is there an easy way to perhaps say:
//pseudo code:
if (peckedSquare.ImageName == pigeon1.png)
{
System.Diagnostics.Debug.WriteLine("Pecked Pigeon number 1");
}
I have googled my query but I have not found any suitable answers.
//EDIT
I have just re-read my code.
I was assigning each picture to a picturebox square using a randomnumber.
I had this random number as a variable, so I can just use that variable to determine which image was clicked.
ie.
if (randomNumber == 1)
{
System.Diagnostics.Debug.WriteLine("Pecked Pigeon number 1");
}
or better than that
pigeonSelected = randomNumber + 1 //as I am using an array to store the images
System.Diagnostics.Debug.WriteLine("Pecked Pigeon Number {0}", pigeonSelected);
As quick & dirty solution I would use Tag property for that, null for black tiles and file path for the others (and it's always available, even if your image comes from resources), something like this:
if (peckedSquare.Tag == null)
{
Debug.WriteLine("Pecked a black square");
}
else
{
switch (Path.GetFileName(peckedSquare.Tag.ToString()))
{
case "pigeon1.png":
break;
}
}
Of course when you create tiles you have to store file path in Tag:
PictureBox tile = new PictureBox();
tile.Image = Image.FromFile(path); // Or another source, of course
tile.Tag = path;
As alternative you may even use Name property for this, each control is named (primary for designer-code integration) but if you create controls at run-time you can set that value to anything you want (not only valid identifiers). Same usage as above just no need to call ToString().
How to Improve?
Please let me say this solution is not very OOP. Even without a big refactoring we can do little bit better. Note that you can store whatever you want in Tag property. A number, a simple string unrelated to file name or even (maybe better) a class or an enum that represents that image (to delegate action to that object). This is a very raw example:
abstract class Tile {
public abstract void Activate();
}
sealed class EmptyTile : Tile {
public virtual void Activate() {
Debug.WriteLine("Pecked a black square");
}
}
sealed class ImageTile : Tile {
public ImageTile(string content) {
_content = content;
}
public virtual void Activate() {
Debug.WriteLine(_content);
}
private string _content;
}
In this way in your click event handler you can do this:
((Tile)peckedTile.Tag).Activate();
No need to check what's inside or to compare with null. No if and no switch, just don't forget to put proper object (ImageTile or BlackTile) when you create tiles.
Use PictureBox.Load(string) method to load images from file. Then the file path will be stored in the
PictureBox.ImageLocation property:
A call to the Load method will overwrite the ImageLocation property, setting ImageLocation to the URL value specified in the method call.
So you can write for example:
if (peckedSquare.ImageLocation.EndsWith("pigeon1.png"))
{
System.Diagnostics.Debug.WriteLine("Pecked Pigeon number 1");
}
I think you could do something like the following:
private List<PictureBox> pictures = null;
string[] ImageNames = new string[]
{
"images\\test_1.jpg",
"images\\test_2.jpg"
};
private void Form1_Load(object sender, EventArgs e)
{
pictures = new List<PictureBox>();
for (var idx = 0; idx < ImageNames.Length; idx++)
{
pictures.Add(new PictureBox());
pictures[idx].Image = new Bitmap(ImageNames[idx]);
pictures[idx].Click += OnClick;
// you'll want to set the offset and everything so it shows at the right place
Controls.Add(pictures[idx]);
}
}
private void OnClick(object sender, EventArgs eventArgs)
{
// you'll definitely want error handling here
var ImageName = ImageNames[pictures.IndexOf((PictureBox) sender)];
}
You can see that in the click method you will be able to get the image name, which is what you are looking for I believe.
As others have said, you can also use the "Tag" property assuming you weren't already using this for some other purpose. The nice thing about tag is you can probably also edit it through the form designer which allows you to lay things out a little more nicely than the automatic layout I used above. Good luck!
You can do something like this using the Tag property like #Adriano suggested:
public Form1()
{
InitializeComponent();
pictureBox1.Click += pictureBox_Click;
pictureBox2.Click += pictureBox_Click;
pictureBox3.Click += pictureBox_Click;
// ...
pictureBox1.Tag = "picture1.png";
pictureBox2.Tag = "picture2.png";
pictureBox3.Tag = "picture3.png";
}
void pictureBox_Click(object sender, EventArgs e)
{
PictureBox pb = sender as PictureBox;
if (pb.BackColor != Color.Black)
Debug.WriteLine(pb.Tag.ToString());
else
Debug.WriteLine("Black image");
}

Pause a GIF in a form

Just wondering how could you go about pausing a GIF image?
I'm accessing a server and I want a gif image to play when something is happening and if the system has froze I want it to pause.
I have a picturebox with the image attached to it.
Is this possible?
PictureBox uses the ImageAnimator class to animate a GIF image. Which has the Stop() method to stop the animation. Unfortunately it doesn't expose the members you need to tinker with it, you'd have to use ImageAnimator yourself.
If you are not against using Reflection to hack around these restrictions then you could use a back-door. It is normally a fairly bad idea, but Winforms is in maintenance mode and the odds that PictureBox is ever going to change again are very close to zero. It looks like this:
using System.Reflection;
...
private static bool IsAnimating(PictureBox box) {
var fi = box.GetType().GetField("currentlyAnimating",
BindingFlags.NonPublic | BindingFlags.Instance);
return (bool)fi.GetValue(box);
}
private static void Animate(PictureBox box, bool enable) {
var anim = box.GetType().GetMethod("Animate",
BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(bool) }, null);
anim.Invoke(box, new object[] { enable });
}
This sample button's Click event reliably stopped and started the animation:
private void button1_Click(object sender, EventArgs e) {
Animate(pictureBox1, !IsAnimating(pictureBox1));
}
If you don't care for these kind of hacks then use ImageAnimator yourself.
Convert the desired frame to a bitmap
Image gifImg = ActivscreenLibraries.Resources.throbber_running;
FrameDimension dimension = new FrameDimension(gifImg.FrameDimensionsList[0]);
// Number of frames
int frameCount = gifImg.GetFrameCount(dimension);
// Return an Image at a certain index
gifImg.SelectActiveFrame(dimension, 5);
Bitmap aa = new Bitmap(gifImg);
pictureBox1.Image = Image.FromHbitmap(aa.GetHbitmap());
As you can read in comments to the question Micha has linked you can simple set
myPictureBox.Enabled = false;
to stop image animation. Set it to true to start it again. The is no need for Reflections.
Windows.Forms.PictureBox.OnEnabledChanged essentially calls Animate(Enabled). See the source code.

Exception: Parameter is not valid (on passing new image to pictureBox)

I already had an image inside PictureBox control, and now I want to pass a new one to it.
What happens, is that allpication Disposes (and I catch an exception: "Parameter is not valid").
This is my code:
using (Image img = Image.FromFile(open.FileName))
{
part.Picture = img;
pictureBox1.InitialImage = null;
pictureBox1.Image = img;
}
So when the code goes out of the method, it goes streight to Displose of this and main form. I catch the exception only on line where Form1 was started. On this one there is no excpetions what so ever.
It must be something wrong while pictureBox is painting (inside Paint event), but I am not surbsribed to it.
I really dont have any more clue how to salve this issue. I have even tried to use to clear all resources (by calling garbage collection), but nothing seems to work.
One more thing: "part" is a reference of the List, so when I try to Delete the current image (to replace it with a new one) I got another exception, like:
"The process cannot access the file because it is being used by another process".
Does this has something to do with the 1st exception (when new image is not painted in pictureBox)?
As Reed noted, the Image you are pulling from open.Filename is being disposed once you exit the using() statement. Your picturebox is still referencing this image in memory, so when it is disposed, you lose what was stored in your picturebox too.
What you really need is a unique copy of the image you are pulling.
using (Image sourceImg = Image.FromFile(open.Filename))
{
Image clonedImg = new Bitmap(sourceImg.Width, sourceImg.Height, PixelFormat.Format32bppArgb);
using (var copy = Graphics.FromImage(clonedImg))
{
copy.DrawImage(sourceImg, 0, 0);
}
pictureBox1.InitialImage = null;
pictureBox1.Image = clonedImg;
}
This way, your file will be unlocked as soon as you exit this block, and you'll keep a unique copy of your image in the picturebox.
The problem is that, after this code executes, pictureBox1.Image is referring to an Image which has been disposed.
If you do not wrap the Image creation in a using, it should correct your issue.
Image img = Image.FromFile(open.FileName);
part.Picture = img;
pictureBox1.InitialImage = null;
pictureBox1.Image = img; // You can't dispose of this, or it won't be valid when PictureBox uses it!
You could also do something like the following create a method that loads the images and then pass it back to the Image Control for example this is what I am using when I want to populate an Image Ctrl
I have a windows form with 3 different Images that I want to load but I am only showing the code for One since I call the same method for all 3 Image Controls
#region Codes for browsing for a picture
/// <summary>
/// this.picStudent the name of the Image Control
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStudentPic_Click(object sender, EventArgs e)
{
Image picture = (Image)BrowseForPicture();
this.picStudent.Image = picture;
this.picStudent.SizeMode = PictureBoxSizeMode.StretchImage;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private Bitmap BrowseForPicture()
{
// Bitmap picture = null;
try
{
if (this.fdlgStudentPic.ShowDialog() == DialogResult.OK)
{
byte[] imageBytes = File.ReadAllBytes(this.fdlgStudentPic.FileName);
StudentPic = new Bitmap( this.fdlgStudentPic.FileName);
StuInfo.StudentPic = imageBytes;
}
else
{
StudentPic = Properties.Resources.NoPhotoAvailable;
}
}
catch (Exception)
{
MessageBox.Show("That was not a picture.", "Browse for picture");
StudentPic = this.BrowseForPicture();
}
return StudentPic;
}
#endregion
Yes, this is now working, but strange, I would almost swear I tried this way too.
Ok, never mind, just that it works.
What is troubling me is something else too, which is in my opinion the same as your code, but its not working, its again trying to Dispose application (with same exception).
This is an example code:
using(Image img = Image.FromFile(open.FileName))
{
part.Picture = img;
}
pictureBox1.InitialImage = null;
pictureBox1.Image = part.Picture; //Picture is a propery in a class
Now I pass an actual image into a generic list, and try to assign new image to pictureBox from it, but, again as I said, exception is thrown (and application is terminated).
Why?

Why can't you bind the Size of a windows form to ApplicationSettings?

Update: Solved, with code
I got it working, see my answer below for the code...
Original Post
As Tundey pointed out in his answer to my last question, you can bind nearly everything about a windows forms control to ApplicationSettings pretty effortlessly. So is there really no way to do this with form Size? This tutorial says you need to handle Size explicitly so you can save RestoreBounds instead of size if the window is maximized or minimized. However, I hoped I could just use a property like:
public Size RestoreSize
{
get
{
if (this.WindowState == FormWindowState.Normal)
{
return this.Size;
}
else
{
return this.RestoreBounds.Size;
}
}
set
{
...
}
}
But I can't see a way to bind this in the designer (Size is notably missing from the PropertyBinding list).
I finally came up with a Form subclass that solves this, once and for all. To use it:
Inherit from RestorableForm instead of Form.
Add a binding in (ApplicationSettings) -> (PropertyBinding) to WindowRestoreState.
Call Properties.Settings.Default.Save() when the window is about to close.
Now window position and state will be remembered between sessions. Following the suggestions from other posters below, I included a function ConstrainToScreen that makes sure the window fits nicely on the available displays when restoring itself.
Code
// Consider this code public domain. If you want, you can even tell
// your boss, attractive women, or the other guy in your cube that
// you wrote it. Enjoy!
using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
namespace Utilities
{
public class RestorableForm : Form, INotifyPropertyChanged
{
// We invoke this event when the binding needs to be updated.
public event PropertyChangedEventHandler PropertyChanged;
// This stores the last window position and state
private WindowRestoreStateInfo windowRestoreState;
// Now we define the property that we will bind to our settings.
[Browsable(false)] // Don't show it in the Properties list
[SettingsBindable(true)] // But do enable binding to settings
public WindowRestoreStateInfo WindowRestoreState
{
get { return windowRestoreState; }
set
{
windowRestoreState = value;
if (PropertyChanged != null)
{
// If anybody's listening, let them know the
// binding needs to be updated:
PropertyChanged(this,
new PropertyChangedEventArgs("WindowRestoreState"));
}
}
}
protected override void OnClosing(CancelEventArgs e)
{
WindowRestoreState = new WindowRestoreStateInfo();
WindowRestoreState.Bounds
= WindowState == FormWindowState.Normal ?
Bounds : RestoreBounds;
WindowRestoreState.WindowState = WindowState;
base.OnClosing(e);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (WindowRestoreState != null)
{
Bounds = ConstrainToScreen(WindowRestoreState.Bounds);
WindowState = WindowRestoreState.WindowState;
}
}
// This helper class stores both position and state.
// That way, we only have to set one binding.
public class WindowRestoreStateInfo
{
Rectangle bounds;
public Rectangle Bounds
{
get { return bounds; }
set { bounds = value; }
}
FormWindowState windowState;
public FormWindowState WindowState
{
get { return windowState; }
set { windowState = value; }
}
}
private Rectangle ConstrainToScreen(Rectangle bounds)
{
Screen screen = Screen.FromRectangle(WindowRestoreState.Bounds);
Rectangle workingArea = screen.WorkingArea;
int width = Math.Min(bounds.Width, workingArea.Width);
int height = Math.Min(bounds.Height, workingArea.Height);
// mmm....minimax
int left = Math.Min(workingArea.Right - width,
Math.Max(bounds.Left, workingArea.Left));
int top = Math.Min(workingArea.Bottom - height,
Math.Max(bounds.Top, workingArea.Top));
return new Rectangle(left, top, width, height);
}
}
}
Settings Bindings References
SettingsBindableAttribute
INotifyPropertyChanged
The reason why the Form.Size property is not available in the settings binding UI is because this property is marked DesignerSerializationVisibility.Hidden. This means that the designer doesn't know how to serialise it, let alone generate a data binding for it. Instead the Form.ClientSize property is the one that gets serialised.
If you try and get clever by binding Location and ClientSize, you'll see another problem. When you try to resize your form from the left or top edge, you'll see weird behaviour. This is apparently related to the way that two-way data binding works in the context of property sets that mutually affect each other. Both Location and ClientSize eventually call into a common method, SetBoundsCore().
Also, data binding to properties like Location and Size is just not efficient. Each time the user moves or resizes the form, Windows sends hundreds of messages to the form, causing the data binding logic to do a lot of processing, when all you really want is to store the last position and size before the form is closed.
This is a very simplified version of what I do:
private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
Properties.Settings.Default.MyState = this.WindowState;
if (this.WindowState == FormWindowState.Normal)
{
Properties.Settings.Default.MySize = this.Size;
Properties.Settings.Default.MyLoc = this.Location;
}
else
{
Properties.Settings.Default.MySize = this.RestoreBounds.Size;
Properties.Settings.Default.MyLoc = this.RestoreBounds.Location;
}
Properties.Settings.Default.Save();
}
private void MyForm_Load(object sender, EventArgs e)
{
this.Size = Properties.Settings.Default.MySize;
this.Location = Properties.Settings.Default.MyLoc;
this.WindowState = Properties.Settings.Default.MyState;
}
Why is this a very simplified version? Because doing this properly is a lot trickier than it looks :-)
One of the reason I imagine size binding is not allowed is because the screen may change between sessions.
Loading the size back when the resolution has reduced could result in the title bar being beyond the limits of the screen.
You also need to be wary of multiple monitor setups, where monitors may no longer be available when you app next runs.
Well I have had a quick play with this and you are correct, while there is no way to directly bind the size of the form to AppSettings, you can add your own values and change the size on load.
I would perhaps recommend that if this is a common feature, you subclass Form and make it automatically prob the App.Config for the forms size settings.
(Or you could roll your own file.. Get it to query an Xml file "formname.settings.xml" or something? - thinking out loud!)..
Heres what I had (very rough, no error checking etc).
App.Config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key ="FormHeight" value="500" />
<add key ="FormWidth" value="200"/>
</appSettings>
</configuration>
Form Code
private void Form1_Load(object sender, EventArgs e)
{
string height = ConfigurationManager.AppSettings["FormHeight"];
int h = int.Parse(height);
string width = ConfigurationManager.AppSettings["FormWidth"];
int w = int.Parse(width);
this.Size = new Size(h, w);
}
I agree with Rob Cooper's answer. But I think Martin makes a very good point. Nothing like having users open your application and the app is off-screen!
So in reality, you'll want to combine both answers and bear in mind the current screen dimensions before setting your form's size.

Categories