1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2005 Novell, Inc.
23 // Jackson Harper (jackson@ximian.com)
29 using System.ComponentModel;
30 using System.ComponentModel.Design;
32 using System.Drawing.Imaging;
33 using System.Runtime.InteropServices;
37 namespace System.Windows.Forms {
38 [DefaultProperty("Image")]
39 [Designer("System.Windows.Forms.Design.PictureBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
41 [Docking (DockingBehavior.Ask)]
42 [ClassInterface (ClassInterfaceType.AutoDispatch)]
44 [DefaultBindingProperty ("Image")]
46 public class PictureBox : Control
53 private PictureBoxSizeMode size_mode;
55 private Image error_image;
56 private string image_location;
57 private Image initial_image;
58 private bool wait_on_load;
59 private WebClient image_download;
61 private int no_update;
64 private EventHandler frame_handler;
66 #region Public Constructor
71 SetStyle (ControlStyles.OptimizedDoubleBuffer, true);
73 SetStyle (ControlStyles.DoubleBuffer, true);
75 SetStyle (ControlStyles.Opaque, false);
76 SetStyle (ControlStyles.Selectable, false);
77 SetStyle (ControlStyles.SupportsTransparentBackColor, true);
78 HandleCreated += new EventHandler(PictureBox_HandleCreated);
80 initial_image = ResourceImageLoader.Get ("image-x-generic.png");
81 error_image = ResourceImageLoader.Get ("image-missing.png");
84 #endregion // Public Constructor
86 #region Public Properties
87 [DefaultValue(PictureBoxSizeMode.Normal)]
89 [RefreshProperties(RefreshProperties.Repaint)]
90 public PictureBoxSizeMode SizeMode {
91 get { return size_mode; }
93 if (size_mode == value)
98 if (size_mode == PictureBoxSizeMode.AutoSize) {
100 SetAutoSizeMode (AutoSizeMode.GrowAndShrink);
103 SetAutoSizeMode (AutoSizeMode.GrowOnly);
107 if (no_update == 0) {
111 OnSizeModeChanged (EventArgs.Empty);
122 get { return image; }
128 if (IsHandleCreated) {
130 if (image != null && ImageAnimator.CanAnimate (image)) {
131 frame_handler = new EventHandler (OnAnimateImage);
132 ImageAnimator.Animate (image, frame_handler);
134 if (no_update == 0) {
141 [DefaultValue(BorderStyle.None)]
143 public BorderStyle BorderStyle {
144 get { return InternalBorderStyle; }
145 set { InternalBorderStyle = value; }
149 [EditorBrowsable(EditorBrowsableState.Never)]
150 public new bool CausesValidation {
151 get { return base.CausesValidation; }
152 set { base.CausesValidation = value; }
157 [RefreshProperties (RefreshProperties.All)]
158 public Image ErrorImage {
159 get { return error_image; }
160 set { error_image = value; }
163 [RefreshProperties (RefreshProperties.All)]
165 public Image InitialImage {
166 get { return initial_image; }
167 set { initial_image = value; }
171 [DefaultValue (null)]
172 [RefreshProperties (RefreshProperties.All)]
173 public string ImageLocation {
174 get { return image_location; }
175 set { image_location = value; }
179 [DefaultValue (false)]
180 public bool WaitOnLoad {
181 get { return wait_on_load; }
182 set { wait_on_load = value; }
187 [EditorBrowsable(EditorBrowsableState.Never)]
188 public new ImeMode ImeMode {
189 get { return base.ImeMode; }
190 set { base.ImeMode = value; }
194 [EditorBrowsable(EditorBrowsableState.Never)]
195 public override RightToLeft RightToLeft {
196 get { return base.RightToLeft; }
197 set { base.RightToLeft = value; }
201 [EditorBrowsable(EditorBrowsableState.Never)]
202 public new int TabIndex {
203 get { return base.TabIndex; }
204 set { base.TabIndex = value; }
208 [EditorBrowsable(EditorBrowsableState.Never)]
209 public new bool TabStop {
210 get { return base.TabStop; }
211 set { base.TabStop = value; }
216 [EditorBrowsable(EditorBrowsableState.Never)]
217 public override string Text {
218 get { return base.Text; }
219 set { base.Text = value; }
222 protected override CreateParams CreateParams {
224 return base.CreateParams;
228 protected override ImeMode DefaultImeMode {
229 get { return base.DefaultImeMode; }
233 [EditorBrowsable(EditorBrowsableState.Never)]
234 public override Font Font {
235 get { return base.Font; }
236 set { base.Font = value; }
240 [EditorBrowsable(EditorBrowsableState.Never)]
241 public override Color ForeColor {
242 get { return base.ForeColor; }
243 set { base.ForeColor = value; }
247 [EditorBrowsable(EditorBrowsableState.Never)]
248 public override bool AllowDrop {
249 get { return base.AllowDrop; }
250 set { base.AllowDrop = value; }
252 #endregion // Public Properties
254 #region Protected Instance Methods
255 protected override Size DefaultSize {
256 get { return ThemeEngine.Current.PictureBoxDefaultSize; }
259 protected override void Dispose (bool disposing)
266 initial_image = null;
269 base.Dispose (disposing);
272 protected override void OnPaint (PaintEventArgs pe)
274 ThemeEngine.Current.DrawPictureBox (pe.Graphics, pe.ClipRectangle, this);
278 protected override void OnVisibleChanged (EventArgs e)
280 base.OnVisibleChanged (e);
283 protected virtual void OnSizeModeChanged (EventArgs e)
285 EventHandler eh = (EventHandler)(Events [SizeModeChangedEvent]);
290 protected override void OnEnabledChanged (EventArgs e)
292 base.OnEnabledChanged (e);
296 [EditorBrowsable (EditorBrowsableState.Advanced)]
297 protected override void OnHandleCreated (EventArgs e)
299 base.OnHandleCreated (e);
302 [EditorBrowsable (EditorBrowsableState.Advanced)]
303 protected override void OnHandleDestroyed (EventArgs e)
305 base.OnHandleDestroyed (e);
308 protected virtual void OnLoadCompleted (AsyncCompletedEventArgs e)
310 AsyncCompletedEventHandler eh = (AsyncCompletedEventHandler)(Events[LoadCompletedEvent]);
315 protected virtual void OnLoadProgressChanged (ProgressChangedEventArgs e)
317 ProgressChangedEventHandler eh = (ProgressChangedEventHandler)(Events[LoadProgressChangedEvent]);
323 protected override void OnParentChanged (EventArgs e)
325 base.OnParentChanged (e);
328 protected override void OnResize (EventArgs e)
332 if (size_mode == PictureBoxSizeMode.CenterImage || size_mode == PictureBoxSizeMode.StretchImage)
335 if (size_mode == PictureBoxSizeMode.Zoom)
341 internal override Size GetPreferredSizeCore (Size proposedSize)
344 return base.GetPreferredSizeCore (proposedSize);
349 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
351 if (size_mode == PictureBoxSizeMode.AutoSize && image != null) {
353 height = image.Height;
355 base.SetBoundsCore (x, y, width, height, specified);
358 #endregion // Protected Instance Methods
361 #region ISupportInitialize Interface
362 void System.ComponentModel.ISupportInitialize.BeginInit() {
366 void System.ComponentModel.ISupportInitialize.EndInit() {
370 if (no_update == 0) {
374 #endregion // ISupportInitialize Interface
377 #region Private Properties
379 private WebClient ImageDownload {
381 if (image_download == null)
382 image_download = new WebClient ();
384 return image_download;
390 #region Private Methods
391 private void StopAnimation ()
393 if (frame_handler == null)
395 ImageAnimator.StopAnimate (image, frame_handler);
396 frame_handler = null;
399 private void UpdateSize ()
405 Parent.PerformLayout (this, "AutoSize");
407 if (size_mode == PictureBoxSizeMode.AutoSize)
408 ClientSize = image.Size;
412 private void OnAnimateImage (object sender, EventArgs e)
414 // This is called from a worker thread,BeginInvoke is used
415 // so the control is updated from the correct thread
417 // Check if we have a handle again, since it may have gotten
418 // destroyed since the last time we checked.
419 if (!IsHandleCreated)
422 BeginInvoke (new EventHandler (UpdateAnimatedImage), new object [] { this, e });
425 private void UpdateAnimatedImage (object sender, EventArgs e)
427 // Check if we have a handle again, since it may have gotten
428 // destroyed since the last time we checked.
429 if (!IsHandleCreated)
432 ImageAnimator.UpdateFrames (image);
436 private void PictureBox_HandleCreated(object sender, EventArgs e) {
438 if (image != null && ImageAnimator.CanAnimate (image)) {
439 frame_handler = new EventHandler (OnAnimateImage);
440 ImageAnimator.Animate (image, frame_handler);
442 if (no_update == 0) {
448 void ImageDownload_DownloadDataCompleted (object sender, DownloadDataCompletedEventArgs e)
450 if (e.Error != null && !e.Cancelled)
452 else if (e.Error == null && !e.Cancelled)
453 using (MemoryStream ms = new MemoryStream (e.Result))
454 Image = Image.FromStream (ms);
456 ImageDownload.DownloadProgressChanged -= new DownloadProgressChangedEventHandler (ImageDownload_DownloadProgressChanged);
457 ImageDownload.DownloadDataCompleted -= new DownloadDataCompletedEventHandler (ImageDownload_DownloadDataCompleted);
458 image_download = null;
463 private void ImageDownload_DownloadProgressChanged (object sender, DownloadProgressChangedEventArgs e)
465 OnLoadProgressChanged (new ProgressChangedEventArgs (e.ProgressPercentage, e.UserState));
468 #endregion // Private Methods
470 #region Public Instance Methods
472 public void CancelAsync ()
474 if (image_download != null)
475 image_download.CancelAsync ();
480 Load (image_location);
483 public void Load (string url)
485 if (string.IsNullOrEmpty (url))
486 throw new InvalidOperationException ("ImageLocation not specified.");
488 image_location = url;
490 if (url.Contains ("://"))
491 using (Stream s = ImageDownload.OpenRead (url))
492 Image = Image.FromStream (s);
494 Image = Image.FromFile (url);
497 public void LoadAsync ()
499 LoadAsync (image_location);
502 public void LoadAsync (string url)
504 // If WaitOnLoad is true, do not do async
509 image_location = url;
510 Image = InitialImage;
512 if (ImageDownload.IsBusy)
513 ImageDownload.CancelAsync ();
515 ImageDownload.DownloadProgressChanged += new DownloadProgressChangedEventHandler (ImageDownload_DownloadProgressChanged);
516 ImageDownload.DownloadDataCompleted += new DownloadDataCompletedEventHandler (ImageDownload_DownloadDataCompleted);
517 ImageDownload.DownloadDataAsync (new Uri (url));
520 public override string ToString() {
521 return String.Format("{0}, SizeMode: {1}", base.ToString (), SizeMode);
527 [EditorBrowsable(EditorBrowsableState.Never)]
528 public new event EventHandler CausesValidationChanged {
529 add { base.CausesValidationChanged += value; }
530 remove { base.CausesValidationChanged -= value; }
534 [EditorBrowsable(EditorBrowsableState.Never)]
535 public new event EventHandler Enter {
536 add { base.Enter += value; }
537 remove { base.Enter -= value; }
541 [EditorBrowsable(EditorBrowsableState.Never)]
542 public new event EventHandler FontChanged {
543 add { base.FontChanged += value; }
544 remove { base.FontChanged -= value; }
548 [EditorBrowsable(EditorBrowsableState.Never)]
549 public new event EventHandler ForeColorChanged {
550 add { base.ForeColorChanged += value; }
551 remove { base.ForeColorChanged -= value; }
555 [EditorBrowsable(EditorBrowsableState.Never)]
556 public new event EventHandler ImeModeChanged {
557 add { base.ImeModeChanged += value; }
558 remove { base.ImeModeChanged -= value; }
562 [EditorBrowsable(EditorBrowsableState.Never)]
563 public new event KeyEventHandler KeyDown {
564 add { base.KeyDown += value; }
565 remove { base.KeyDown -= value; }
569 [EditorBrowsable(EditorBrowsableState.Never)]
570 public new event KeyPressEventHandler KeyPress {
571 add { base.KeyPress += value; }
572 remove { base.KeyPress -= value; }
576 [EditorBrowsable(EditorBrowsableState.Never)]
577 public new event KeyEventHandler KeyUp {
578 add { base.KeyUp += value; }
579 remove { base.KeyUp -= value; }
583 [EditorBrowsable(EditorBrowsableState.Never)]
584 public new event EventHandler Leave {
585 add { base.Leave += value; }
586 remove { base.Leave -= value; }
590 static object LoadCompletedEvent = new object ();
591 static object LoadProgressChangedEvent = new object ();
593 public event AsyncCompletedEventHandler LoadCompleted {
594 add { Events.AddHandler (LoadCompletedEvent, value); }
595 remove { Events.RemoveHandler (LoadCompletedEvent, value); }
598 public event ProgressChangedEventHandler LoadProgressChanged {
599 add { Events.AddHandler (LoadProgressChangedEvent, value); }
600 remove { Events.RemoveHandler (LoadProgressChangedEvent, value); }
605 [EditorBrowsable(EditorBrowsableState.Never)]
606 public new event EventHandler RightToLeftChanged {
607 add { base.RightToLeftChanged += value; }
608 remove { base.RightToLeftChanged -= value; }
612 [EditorBrowsable(EditorBrowsableState.Never)]
613 public new event EventHandler TabIndexChanged {
614 add { base.TabIndexChanged += value; }
615 remove { base.TabIndexChanged -= value; }
619 [EditorBrowsable(EditorBrowsableState.Never)]
620 public new event EventHandler TabStopChanged {
621 add { base.TabStopChanged += value; }
622 remove { base.TabStopChanged -= value; }
626 [EditorBrowsable(EditorBrowsableState.Never)]
627 public new event EventHandler TextChanged {
628 add { base.TextChanged += value; }
629 remove { base.TextChanged -= value; }
632 static object SizeModeChangedEvent = new object ();
633 public event EventHandler SizeModeChanged {
634 add { Events.AddHandler (SizeModeChangedEvent, value); }
635 remove { Events.RemoveHandler (SizeModeChangedEvent, value); }