using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
+using System.IO;
+using System.Net;
namespace System.Windows.Forms {
[DefaultProperty("Image")]
[Designer("System.Windows.Forms.Design.PictureBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
- public class PictureBox : Control
-#if NET_2_0
- , ISupportInitialize
-#endif
+ [Docking (DockingBehavior.Ask)]
+ [ClassInterface (ClassInterfaceType.AutoDispatch)]
+ [ComVisible (true)]
+ [DefaultBindingProperty ("Image")]
+ public class PictureBox : Control, ISupportInitialize
{
#region Fields
private Image image;
private PictureBoxSizeMode size_mode;
- private bool redraw;
- private bool recalc;
- private bool allow_drop;
+ private Image error_image;
+ private string image_location;
private Image initial_image;
+ private bool wait_on_load;
+ private WebClient image_download;
+ private bool image_from_url;
private int no_update;
#endregion // Fields
#region Public Constructor
public PictureBox ()
{
- redraw = true;
- recalc = true;
- allow_drop = false;
-#if NET_2_0
+ //recalc = true;
+ no_update = 0;
+
SetStyle (ControlStyles.OptimizedDoubleBuffer, true);
-#else
- SetStyle (ControlStyles.DoubleBuffer, true);
-#endif
SetStyle (ControlStyles.Opaque, false);
SetStyle (ControlStyles.Selectable, false);
SetStyle (ControlStyles.SupportsTransparentBackColor, true);
HandleCreated += new EventHandler(PictureBox_HandleCreated);
+ initial_image = ResourceImageLoader.Get ("image-x-generic.png");
+ error_image = ResourceImageLoader.Get ("image-missing.png");
}
#endregion // Public Constructor
if (size_mode == value)
return;
size_mode = value;
+
+ if (size_mode == PictureBoxSizeMode.AutoSize) {
+ AutoSize = true;
+ SetAutoSizeMode (AutoSizeMode.GrowAndShrink);
+ } else {
+ AutoSize = false;
+ SetAutoSizeMode (AutoSizeMode.GrowOnly);
+ }
+
UpdateSize ();
if (no_update == 0) {
- Redraw (true);
Invalidate ();
}
}
}
- [DefaultValue(null)]
+ [Bindable (true)]
[Localizable(true)]
public Image Image {
get { return image; }
- set {
- StopAnimation ();
-
- image = value;
-
- if (IsHandleCreated) {
- UpdateSize ();
- if (image != null && ImageAnimator.CanAnimate (image)) {
- frame_handler = new EventHandler (OnAnimateImage);
- ImageAnimator.Animate (image, frame_handler);
- }
- if (no_update == 0) {
- Redraw (true);
- Invalidate ();
- }
- }
- }
+ set { ChangeImage (value, false); }
}
[DefaultValue(BorderStyle.None)]
set { base.CausesValidation = value; }
}
-#if NET_2_0
- [DefaultValue(null)]
+ [Localizable (true)]
+ [RefreshProperties (RefreshProperties.All)]
+ public Image ErrorImage {
+ get { return error_image; }
+ set { error_image = value; }
+ }
+
+ [RefreshProperties (RefreshProperties.All)]
[Localizable(true)]
public Image InitialImage {
get { return initial_image; }
set { initial_image = value; }
}
-#endif
+
+ [Localizable (true)]
+ [DefaultValue (null)]
+ [RefreshProperties (RefreshProperties.All)]
+ public string ImageLocation {
+ get { return image_location; }
+ set {
+ image_location = value;
+
+ if (!string.IsNullOrEmpty (value)) {
+ if (WaitOnLoad)
+ Load (value);
+ else
+ LoadAsync (value);
+ } else if (image_from_url)
+ ChangeImage (null, true);
+ }
+ }
+
+ [Localizable (true)]
+ [DefaultValue (false)]
+ public bool WaitOnLoad {
+ get { return wait_on_load; }
+ set { wait_on_load = value; }
+ }
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool AllowDrop {
- get {
- return allow_drop;
- }
- set {
- if (allow_drop != value) {
- allow_drop = value;
- }
- }
+ get { return base.AllowDrop; }
+ set { base.AllowDrop = value; }
}
#endregion // Public Properties
protected override void OnPaint (PaintEventArgs pe)
{
- ThemeEngine.Current.DrawPictureBox (pe.Graphics, pe.ClipRectangle, this);
+ ThemeEngine.Current.DrawPictureBox (pe.Graphics, pe.ClipRectangle, this);
base.OnPaint (pe);
}
protected override void OnVisibleChanged (EventArgs e)
{
base.OnVisibleChanged (e);
- Redraw (true);
}
protected virtual void OnSizeModeChanged (EventArgs e)
{
- if (SizeModeChanged != null)
- SizeModeChanged (this, e);
+ EventHandler eh = (EventHandler)(Events [SizeModeChangedEvent]);
+ if (eh != null)
+ eh (this, e);
}
protected override void OnEnabledChanged (EventArgs e)
base.OnEnabledChanged (e);
}
+ [EditorBrowsable (EditorBrowsableState.Advanced)]
+ protected override void OnHandleCreated (EventArgs e)
+ {
+ base.OnHandleCreated (e);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Advanced)]
+ protected override void OnHandleDestroyed (EventArgs e)
+ {
+ base.OnHandleDestroyed (e);
+ }
+
+ protected virtual void OnLoadCompleted (AsyncCompletedEventArgs e)
+ {
+ AsyncCompletedEventHandler eh = (AsyncCompletedEventHandler)(Events[LoadCompletedEvent]);
+ if (eh != null)
+ eh (this, e);
+ }
+
+ protected virtual void OnLoadProgressChanged (ProgressChangedEventArgs e)
+ {
+ ProgressChangedEventHandler eh = (ProgressChangedEventHandler)(Events[LoadProgressChangedEvent]);
+ if (eh != null)
+ eh (this, e);
+ }
+
protected override void OnParentChanged (EventArgs e)
{
base.OnParentChanged (e);
protected override void OnResize (EventArgs e)
{
base.OnResize (e);
- redraw = true;
-
- if (size_mode == PictureBoxSizeMode.CenterImage || size_mode == PictureBoxSizeMode.StretchImage)
- Refresh ();
+
+ Invalidate ();
}
- protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
+ internal override Size GetPreferredSizeCore (Size proposedSize)
{
- if (size_mode == PictureBoxSizeMode.AutoSize && image != null) {
- width = image.Width;
- height = image.Height;
- }
- base.SetBoundsCore (x, y, width, height, specified);
+ if (image == null)
+ return base.GetPreferredSizeCore (proposedSize);
+ else
+ return image.Size;
}
#endregion // Protected Instance Methods
-#if NET_2_0
#region ISupportInitialize Interface
void System.ComponentModel.ISupportInitialize.BeginInit() {
no_update++;
no_update--;
}
if (no_update == 0) {
- Redraw (true);
Invalidate ();
}
}
#endregion // ISupportInitialize Interface
-#endif
- #region Private Methods
+ #region Private Properties
+ private WebClient ImageDownload {
+ get {
+ if (image_download == null)
+ image_download = new WebClient ();
+
+ return image_download;
+ }
+ }
+ #endregion
+
+ #region Private Methods
+
+ private void ChangeImage (Image value, bool from_url)
+ {
+ StopAnimation ();
+
+ image_from_url = from_url;
+ image = value;
+
+ if (IsHandleCreated) {
+ UpdateSize ();
+ if (image != null && ImageAnimator.CanAnimate (image)) {
+ frame_handler = new EventHandler (OnAnimateImage);
+ ImageAnimator.Animate (image, frame_handler);
+ }
+ if (no_update == 0) {
+ Invalidate ();
+ }
+ }
+ }
+
private void StopAnimation ()
{
if (frame_handler == null)
{
if (image == null)
return;
- if (size_mode == PictureBoxSizeMode.AutoSize)
- ClientSize = image.Size;
- }
- private void Redraw (bool recalc)
- {
- redraw = true;
- this.recalc = recalc;
+ if (Parent != null)
+ Parent.PerformLayout (this, "AutoSize");
}
private void OnAnimateImage (object sender, EventArgs e)
{
// This is called from a worker thread,BeginInvoke is used
// so the control is updated from the correct thread
+
+ // Check if we have a handle again, since it may have gotten
+ // destroyed since the last time we checked.
+ if (!IsHandleCreated)
+ return;
+
BeginInvoke (new EventHandler (UpdateAnimatedImage), new object [] { this, e });
}
private void UpdateAnimatedImage (object sender, EventArgs e)
{
+ // Check if we have a handle again, since it may have gotten
+ // destroyed since the last time we checked.
+ if (!IsHandleCreated)
+ return;
+
ImageAnimator.UpdateFrames (image);
- Redraw (false);
Refresh ();
}
ImageAnimator.Animate (image, frame_handler);
}
if (no_update == 0) {
- Redraw (true);
Invalidate ();
}
}
+
+ void ImageDownload_DownloadDataCompleted (object sender, DownloadDataCompletedEventArgs e)
+ {
+ if (e.Error != null && !e.Cancelled)
+ Image = error_image;
+ else if (e.Error == null && !e.Cancelled)
+ using (MemoryStream ms = new MemoryStream (e.Result))
+ Image = Image.FromStream (ms);
+
+ ImageDownload.DownloadProgressChanged -= new DownloadProgressChangedEventHandler (ImageDownload_DownloadProgressChanged);
+ ImageDownload.DownloadDataCompleted -= new DownloadDataCompletedEventHandler (ImageDownload_DownloadDataCompleted);
+ image_download = null;
+
+ OnLoadCompleted (e);
+ }
+
+ private void ImageDownload_DownloadProgressChanged (object sender, DownloadProgressChangedEventArgs e)
+ {
+ OnLoadProgressChanged (new ProgressChangedEventArgs (e.ProgressPercentage, e.UserState));
+ }
#endregion // Private Methods
#region Public Instance Methods
+ public void CancelAsync ()
+ {
+ if (image_download != null)
+ image_download.CancelAsync ();
+ }
+
+ public void Load ()
+ {
+ Load (image_location);
+ }
+
+ public void Load (string url)
+ {
+ if (string.IsNullOrEmpty (url))
+ throw new InvalidOperationException ("ImageLocation not specified.");
+
+ image_location = url;
+
+ if (url.Contains ("://"))
+ using (Stream s = ImageDownload.OpenRead (url))
+ ChangeImage (Image.FromStream (s), true);
+ else
+ ChangeImage (Image.FromFile (url), true);
+ }
+
+ public void LoadAsync ()
+ {
+ LoadAsync (image_location);
+ }
+
+ public void LoadAsync (string url)
+ {
+ // If WaitOnLoad is true, do not do async
+ if (wait_on_load) {
+ Load (url);
+ return;
+ }
+
+ if (string.IsNullOrEmpty (url))
+ throw new InvalidOperationException ("ImageLocation not specified.");
+
+ image_location = url;
+ ChangeImage (InitialImage, true);
+
+ if (ImageDownload.IsBusy)
+ ImageDownload.CancelAsync ();
+
+ Uri uri = null;
+ try {
+ uri = new Uri (url);
+ } catch (UriFormatException) {
+ uri = new Uri (Path.GetFullPath (url));
+ }
+
+ ImageDownload.DownloadProgressChanged += new DownloadProgressChangedEventHandler (ImageDownload_DownloadProgressChanged);
+ ImageDownload.DownloadDataCompleted += new DownloadDataCompletedEventHandler (ImageDownload_DownloadDataCompleted);
+ ImageDownload.DownloadDataAsync (uri);
+ }
+
public override string ToString() {
return String.Format("{0}, SizeMode: {1}", base.ToString (), SizeMode);
}
remove { base.Leave -= value; }
}
+ static object LoadCompletedEvent = new object ();
+ static object LoadProgressChangedEvent = new object ();
+
+ public event AsyncCompletedEventHandler LoadCompleted {
+ add { Events.AddHandler (LoadCompletedEvent, value); }
+ remove { Events.RemoveHandler (LoadCompletedEvent, value); }
+ }
+
+ public event ProgressChangedEventHandler LoadProgressChanged {
+ add { Events.AddHandler (LoadProgressChangedEvent, value); }
+ remove { Events.RemoveHandler (LoadProgressChangedEvent, value); }
+ }
+
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public new event EventHandler RightToLeftChanged {
remove { base.TextChanged -= value; }
}
- public event EventHandler SizeModeChanged;
+ static object SizeModeChangedEvent = new object ();
+ public event EventHandler SizeModeChanged {
+ add { Events.AddHandler (SizeModeChangedEvent, value); }
+ remove { Events.RemoveHandler (SizeModeChangedEvent, value); }
+ }
+
#endregion // Events
}
}