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; }
176 image_location = value;
182 [DefaultValue (false)]
183 public bool WaitOnLoad {
184 get { return wait_on_load; }
185 set { wait_on_load = value; }
190 [EditorBrowsable(EditorBrowsableState.Never)]
191 public new ImeMode ImeMode {
192 get { return base.ImeMode; }
193 set { base.ImeMode = value; }
197 [EditorBrowsable(EditorBrowsableState.Never)]
198 public override RightToLeft RightToLeft {
199 get { return base.RightToLeft; }
200 set { base.RightToLeft = value; }
204 [EditorBrowsable(EditorBrowsableState.Never)]
205 public new int TabIndex {
206 get { return base.TabIndex; }
207 set { base.TabIndex = value; }
211 [EditorBrowsable(EditorBrowsableState.Never)]
212 public new bool TabStop {
213 get { return base.TabStop; }
214 set { base.TabStop = value; }
219 [EditorBrowsable(EditorBrowsableState.Never)]
220 public override string Text {
221 get { return base.Text; }
222 set { base.Text = value; }
225 protected override CreateParams CreateParams {
227 return base.CreateParams;
231 protected override ImeMode DefaultImeMode {
232 get { return base.DefaultImeMode; }
236 [EditorBrowsable(EditorBrowsableState.Never)]
237 public override Font Font {
238 get { return base.Font; }
239 set { base.Font = value; }
243 [EditorBrowsable(EditorBrowsableState.Never)]
244 public override Color ForeColor {
245 get { return base.ForeColor; }
246 set { base.ForeColor = value; }
250 [EditorBrowsable(EditorBrowsableState.Never)]
251 public override bool AllowDrop {
252 get { return base.AllowDrop; }
253 set { base.AllowDrop = value; }
255 #endregion // Public Properties
257 #region Protected Instance Methods
258 protected override Size DefaultSize {
259 get { return ThemeEngine.Current.PictureBoxDefaultSize; }
262 protected override void Dispose (bool disposing)
269 initial_image = null;
272 base.Dispose (disposing);
275 protected override void OnPaint (PaintEventArgs pe)
277 ThemeEngine.Current.DrawPictureBox (pe.Graphics, pe.ClipRectangle, this);
281 protected override void OnVisibleChanged (EventArgs e)
283 base.OnVisibleChanged (e);
286 protected virtual void OnSizeModeChanged (EventArgs e)
288 EventHandler eh = (EventHandler)(Events [SizeModeChangedEvent]);
293 protected override void OnEnabledChanged (EventArgs e)
295 base.OnEnabledChanged (e);
299 [EditorBrowsable (EditorBrowsableState.Advanced)]
300 protected override void OnHandleCreated (EventArgs e)
302 base.OnHandleCreated (e);
305 [EditorBrowsable (EditorBrowsableState.Advanced)]
306 protected override void OnHandleDestroyed (EventArgs e)
308 base.OnHandleDestroyed (e);
311 protected virtual void OnLoadCompleted (AsyncCompletedEventArgs e)
313 AsyncCompletedEventHandler eh = (AsyncCompletedEventHandler)(Events[LoadCompletedEvent]);
318 protected virtual void OnLoadProgressChanged (ProgressChangedEventArgs e)
320 ProgressChangedEventHandler eh = (ProgressChangedEventHandler)(Events[LoadProgressChangedEvent]);
326 protected override void OnParentChanged (EventArgs e)
328 base.OnParentChanged (e);
331 protected override void OnResize (EventArgs e)
339 internal override Size GetPreferredSizeCore (Size proposedSize)
342 return base.GetPreferredSizeCore (proposedSize);
347 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
349 if (size_mode == PictureBoxSizeMode.AutoSize && image != null) {
351 height = image.Height;
353 base.SetBoundsCore (x, y, width, height, specified);
356 #endregion // Protected Instance Methods
359 #region ISupportInitialize Interface
360 void System.ComponentModel.ISupportInitialize.BeginInit() {
364 void System.ComponentModel.ISupportInitialize.EndInit() {
368 if (no_update == 0) {
372 #endregion // ISupportInitialize Interface
375 #region Private Properties
377 private WebClient ImageDownload {
379 if (image_download == null)
380 image_download = new WebClient ();
382 return image_download;
388 #region Private Methods
389 private void StopAnimation ()
391 if (frame_handler == null)
393 ImageAnimator.StopAnimate (image, frame_handler);
394 frame_handler = null;
397 private void UpdateSize ()
403 Parent.PerformLayout (this, "AutoSize");
405 if (size_mode == PictureBoxSizeMode.AutoSize)
406 ClientSize = image.Size;
410 private void OnAnimateImage (object sender, EventArgs e)
412 // This is called from a worker thread,BeginInvoke is used
413 // so the control is updated from the correct thread
415 // Check if we have a handle again, since it may have gotten
416 // destroyed since the last time we checked.
417 if (!IsHandleCreated)
420 BeginInvoke (new EventHandler (UpdateAnimatedImage), new object [] { this, e });
423 private void UpdateAnimatedImage (object sender, EventArgs e)
425 // Check if we have a handle again, since it may have gotten
426 // destroyed since the last time we checked.
427 if (!IsHandleCreated)
430 ImageAnimator.UpdateFrames (image);
434 private void PictureBox_HandleCreated(object sender, EventArgs e) {
436 if (image != null && ImageAnimator.CanAnimate (image)) {
437 frame_handler = new EventHandler (OnAnimateImage);
438 ImageAnimator.Animate (image, frame_handler);
440 if (no_update == 0) {
446 void ImageDownload_DownloadDataCompleted (object sender, DownloadDataCompletedEventArgs e)
448 if (e.Error != null && !e.Cancelled)
450 else if (e.Error == null && !e.Cancelled)
451 using (MemoryStream ms = new MemoryStream (e.Result))
452 Image = Image.FromStream (ms);
454 ImageDownload.DownloadProgressChanged -= new DownloadProgressChangedEventHandler (ImageDownload_DownloadProgressChanged);
455 ImageDownload.DownloadDataCompleted -= new DownloadDataCompletedEventHandler (ImageDownload_DownloadDataCompleted);
456 image_download = null;
461 private void ImageDownload_DownloadProgressChanged (object sender, DownloadProgressChangedEventArgs e)
463 OnLoadProgressChanged (new ProgressChangedEventArgs (e.ProgressPercentage, e.UserState));
466 #endregion // Private Methods
468 #region Public Instance Methods
470 public void CancelAsync ()
472 if (image_download != null)
473 image_download.CancelAsync ();
478 Load (image_location);
481 public void Load (string url)
483 if (string.IsNullOrEmpty (url))
484 throw new InvalidOperationException ("ImageLocation not specified.");
486 image_location = url;
488 if (url.Contains ("://"))
489 using (Stream s = ImageDownload.OpenRead (url))
490 Image = Image.FromStream (s);
492 Image = Image.FromFile (url);
495 public void LoadAsync ()
497 LoadAsync (image_location);
500 public void LoadAsync (string url)
502 // If WaitOnLoad is true, do not do async
507 image_location = url;
508 Image = InitialImage;
510 if (ImageDownload.IsBusy)
511 ImageDownload.CancelAsync ();
513 ImageDownload.DownloadProgressChanged += new DownloadProgressChangedEventHandler (ImageDownload_DownloadProgressChanged);
514 ImageDownload.DownloadDataCompleted += new DownloadDataCompletedEventHandler (ImageDownload_DownloadDataCompleted);
515 ImageDownload.DownloadDataAsync (new Uri (url));
518 public override string ToString() {
519 return String.Format("{0}, SizeMode: {1}", base.ToString (), SizeMode);
525 [EditorBrowsable(EditorBrowsableState.Never)]
526 public new event EventHandler CausesValidationChanged {
527 add { base.CausesValidationChanged += value; }
528 remove { base.CausesValidationChanged -= value; }
532 [EditorBrowsable(EditorBrowsableState.Never)]
533 public new event EventHandler Enter {
534 add { base.Enter += value; }
535 remove { base.Enter -= value; }
539 [EditorBrowsable(EditorBrowsableState.Never)]
540 public new event EventHandler FontChanged {
541 add { base.FontChanged += value; }
542 remove { base.FontChanged -= value; }
546 [EditorBrowsable(EditorBrowsableState.Never)]
547 public new event EventHandler ForeColorChanged {
548 add { base.ForeColorChanged += value; }
549 remove { base.ForeColorChanged -= value; }
553 [EditorBrowsable(EditorBrowsableState.Never)]
554 public new event EventHandler ImeModeChanged {
555 add { base.ImeModeChanged += value; }
556 remove { base.ImeModeChanged -= value; }
560 [EditorBrowsable(EditorBrowsableState.Never)]
561 public new event KeyEventHandler KeyDown {
562 add { base.KeyDown += value; }
563 remove { base.KeyDown -= value; }
567 [EditorBrowsable(EditorBrowsableState.Never)]
568 public new event KeyPressEventHandler KeyPress {
569 add { base.KeyPress += value; }
570 remove { base.KeyPress -= value; }
574 [EditorBrowsable(EditorBrowsableState.Never)]
575 public new event KeyEventHandler KeyUp {
576 add { base.KeyUp += value; }
577 remove { base.KeyUp -= value; }
581 [EditorBrowsable(EditorBrowsableState.Never)]
582 public new event EventHandler Leave {
583 add { base.Leave += value; }
584 remove { base.Leave -= value; }
588 static object LoadCompletedEvent = new object ();
589 static object LoadProgressChangedEvent = new object ();
591 public event AsyncCompletedEventHandler LoadCompleted {
592 add { Events.AddHandler (LoadCompletedEvent, value); }
593 remove { Events.RemoveHandler (LoadCompletedEvent, value); }
596 public event ProgressChangedEventHandler LoadProgressChanged {
597 add { Events.AddHandler (LoadProgressChangedEvent, value); }
598 remove { Events.RemoveHandler (LoadProgressChangedEvent, value); }
603 [EditorBrowsable(EditorBrowsableState.Never)]
604 public new event EventHandler RightToLeftChanged {
605 add { base.RightToLeftChanged += value; }
606 remove { base.RightToLeftChanged -= value; }
610 [EditorBrowsable(EditorBrowsableState.Never)]
611 public new event EventHandler TabIndexChanged {
612 add { base.TabIndexChanged += value; }
613 remove { base.TabIndexChanged -= value; }
617 [EditorBrowsable(EditorBrowsableState.Never)]
618 public new event EventHandler TabStopChanged {
619 add { base.TabStopChanged += value; }
620 remove { base.TabStopChanged -= value; }
624 [EditorBrowsable(EditorBrowsableState.Never)]
625 public new event EventHandler TextChanged {
626 add { base.TextChanged += value; }
627 remove { base.TextChanged -= value; }
630 static object SizeModeChangedEvent = new object ();
631 public event EventHandler SizeModeChanged {
632 add { Events.AddHandler (SizeModeChangedEvent, value); }
633 remove { Events.RemoveHandler (SizeModeChangedEvent, value); }