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: 8 // 9 // The above copyright notice and this permission notice shall be 10 // included in all copies or substantial portions of the Software. 11 // 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. 19 // 20 // Copyright (c) 2004-2006 Novell, Inc. 21 // 22 // Authors: 23 // Jordi Mas i Hernandez, jordi@ximian.com 24 // Peter Bartok, pbartok@novell.com 25 // 26 // 27 28 // COMPLETE 29 30 using System.ComponentModel; 31 using System.ComponentModel.Design; 32 using System.Drawing; 33 using System.Drawing.Text; 34 using System.Drawing.Imaging; 35 using System.Runtime.InteropServices; 36 using System.Windows.Forms.Theming; 37 38 namespace System.Windows.Forms 39 { 40 [DefaultProperty ("Text")] 41 [Designer ("System.Windows.Forms.Design.LabelDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")] 42 [ClassInterface (ClassInterfaceType.AutoDispatch)] 43 [ComVisible (true)] 44 [ToolboxItem ("System.Windows.Forms.Design.AutoSizeToolboxItem," + Consts.AssemblySystem_Design)] 45 [DefaultBindingProperty ("Text")] 46 public class Label : Control 47 { 48 private bool autosize; 49 private bool auto_ellipsis; 50 private Image image; 51 private bool render_transparent; 52 private FlatStyle flat_style; 53 private bool use_mnemonic; 54 private int image_index = -1; 55 private string image_key = string.Empty; 56 private ImageList image_list; 57 internal ContentAlignment image_align; 58 internal StringFormat string_format; 59 internal ContentAlignment text_align; 60 static SizeF req_witdthsize = new SizeF (0,0); 61 62 #region Events 63 static object AutoSizeChangedEvent = new object (); 64 static object TextAlignChangedEvent = new object (); 65 66 [Browsable (true)] 67 [EditorBrowsable (EditorBrowsableState.Always)] 68 public new event EventHandler AutoSizeChanged { 69 add { Events.AddHandler (AutoSizeChangedEvent, value); } 70 remove { Events.RemoveHandler (AutoSizeChangedEvent, value); } 71 } 72 73 [Browsable(false)] 74 [EditorBrowsable(EditorBrowsableState.Never)] 75 public new event EventHandler BackgroundImageChanged { 76 add { base.BackgroundImageChanged += value; } 77 remove { base.BackgroundImageChanged -= value; } 78 } 79 80 [Browsable (false)] 81 [EditorBrowsable (EditorBrowsableState.Never)] 82 public new event EventHandler BackgroundImageLayoutChanged { 83 add { base.BackgroundImageLayoutChanged += value; } 84 remove { base.BackgroundImageLayoutChanged -= value; } 85 } 86 87 [Browsable(false)] 88 [EditorBrowsable(EditorBrowsableState.Never)] 89 public new event EventHandler ImeModeChanged { 90 add { base.ImeModeChanged += value; } 91 remove { base.ImeModeChanged -= value; } 92 } 93 94 [Browsable(false)] 95 [EditorBrowsable(EditorBrowsableState.Never)] 96 public new event KeyEventHandler KeyDown { 97 add { base.KeyDown += value; } 98 remove { base.KeyDown -= value; } 99 } 100 101 [Browsable(false)] 102 [EditorBrowsable(EditorBrowsableState.Never)] 103 public new event KeyPressEventHandler KeyPress { 104 add { base.KeyPress += value; } 105 remove { base.KeyPress -= value; } 106 } 107 108 [Browsable(false)] 109 [EditorBrowsable(EditorBrowsableState.Never)] 110 public new event KeyEventHandler KeyUp { 111 add { base.KeyUp += value; } 112 remove { base.KeyUp -= value; } 113 } 114 115 [Browsable(false)] 116 [EditorBrowsable(EditorBrowsableState.Never)] 117 public new event EventHandler TabStopChanged { 118 add { base.TabStopChanged += value; } 119 remove { base.TabStopChanged -= value; } 120 } 121 122 public event EventHandler TextAlignChanged { 123 add { Events.AddHandler (TextAlignChangedEvent, value); } 124 remove { Events.RemoveHandler (TextAlignChangedEvent, value); } 125 } 126 #endregion 127 Label()128 public Label () 129 { 130 // Defaults in the Spec 131 autosize = false; 132 TabStop = false; 133 string_format = new StringFormat(); 134 string_format.FormatFlags = StringFormatFlags.LineLimit; 135 TextAlign = ContentAlignment.TopLeft; 136 image = null; 137 UseMnemonic = true; 138 image_list = null; 139 image_align = ContentAlignment.MiddleCenter; 140 SetUseMnemonic (UseMnemonic); 141 flat_style = FlatStyle.Standard; 142 143 SetStyle (ControlStyles.Selectable, false); 144 SetStyle (ControlStyles.ResizeRedraw | 145 ControlStyles.UserPaint | 146 ControlStyles.AllPaintingInWmPaint | 147 ControlStyles.SupportsTransparentBackColor | 148 ControlStyles.OptimizedDoubleBuffer 149 , true); 150 151 HandleCreated += new EventHandler (OnHandleCreatedLB); 152 } 153 154 #region Public Properties 155 156 [DefaultValue (false)] 157 [Browsable (true)] 158 [EditorBrowsable (EditorBrowsableState.Always)] 159 public bool AutoEllipsis { 160 get { return this.auto_ellipsis; } 161 set 162 { 163 if (this.auto_ellipsis != value) { 164 this.auto_ellipsis = value; 165 166 if (this.auto_ellipsis) 167 string_format.Trimming = StringTrimming.EllipsisCharacter; 168 else 169 string_format.Trimming = StringTrimming.Character; 170 171 if (Parent != null) 172 Parent.PerformLayout (this, "AutoEllipsis"); 173 this.Invalidate (); 174 } 175 } 176 } 177 178 [Browsable (true)] 179 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)] 180 [EditorBrowsable (EditorBrowsableState.Always)] 181 [DefaultValue(false)] 182 [Localizable(true)] 183 [RefreshProperties(RefreshProperties.All)] 184 public override bool AutoSize { 185 get { return autosize; } 186 set { 187 if (autosize == value) 188 return; 189 190 base.SetAutoSizeMode (AutoSizeMode.GrowAndShrink); 191 base.AutoSize = value; 192 autosize = value; 193 CalcAutoSize (); 194 Invalidate (); 195 196 OnAutoSizeChanged (EventArgs.Empty); 197 } 198 } 199 200 [Browsable(false)] 201 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] 202 [EditorBrowsable(EditorBrowsableState.Never)] 203 public override Image BackgroundImage { 204 get { return base.BackgroundImage; } 205 set { 206 base.BackgroundImage = value; 207 Invalidate (); 208 } 209 } 210 211 [Browsable (false)] 212 [EditorBrowsable (EditorBrowsableState.Never)] 213 public override ImageLayout BackgroundImageLayout { 214 get { return base.BackgroundImageLayout; } 215 set { base.BackgroundImageLayout = value; } 216 } 217 218 [DefaultValue(BorderStyle.None)] 219 [DispId(-504)] 220 public virtual BorderStyle BorderStyle { 221 get { return InternalBorderStyle; } 222 set { InternalBorderStyle = value; } 223 } 224 225 protected override CreateParams CreateParams { 226 get { 227 CreateParams create_params = base.CreateParams; 228 229 if (BorderStyle != BorderStyle.Fixed3D) 230 return create_params; 231 232 create_params.ExStyle &= ~(int) WindowExStyles.WS_EX_CLIENTEDGE; 233 create_params.ExStyle |= (int)WindowExStyles.WS_EX_STATICEDGE; 234 235 return create_params; 236 } 237 } 238 239 protected override ImeMode DefaultImeMode { 240 get { return ImeMode.Disable;} 241 } 242 243 protected override Padding DefaultMargin { 244 get { return new Padding (3, 0, 3, 0); } 245 } 246 247 protected override Size DefaultSize { 248 get { return ThemeElements.LabelPainter.DefaultSize; } 249 } 250 251 [DefaultValue(FlatStyle.Standard)] 252 public FlatStyle FlatStyle { 253 get { return flat_style; } 254 set { 255 if (!Enum.IsDefined (typeof (FlatStyle), value)) 256 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for FlatStyle", value)); 257 258 if (flat_style == value) 259 return; 260 261 flat_style = value; 262 if (Parent != null) 263 Parent.PerformLayout (this, "FlatStyle"); 264 Invalidate (); 265 } 266 } 267 268 [Localizable(true)] 269 public Image Image { 270 get { 271 if (this.image != null) 272 return this.image; 273 274 if (this.image_index >= 0) 275 if (this.image_list != null) 276 return this.image_list.Images[this.image_index]; 277 278 if (!string.IsNullOrEmpty (this.image_key)) 279 if (this.image_list != null) 280 return this.image_list.Images[this.image_key]; 281 282 return null; 283 } 284 set { 285 if (this.image != value) { 286 this.image = value; 287 this.image_index = -1; 288 this.image_key = string.Empty; 289 this.image_list = null; 290 291 if (this.AutoSize && this.Parent != null) 292 this.Parent.PerformLayout (this, "Image"); 293 294 Invalidate (); 295 } 296 } 297 } 298 299 [DefaultValue(ContentAlignment.MiddleCenter)] 300 [Localizable(true)] 301 public ContentAlignment ImageAlign { 302 get { return image_align; } 303 set { 304 if (!Enum.IsDefined (typeof (ContentAlignment), value)) 305 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for ContentAlignment", value)); 306 307 if (image_align == value) 308 return; 309 310 image_align = value; 311 Invalidate (); 312 } 313 } 314 315 [DefaultValue (-1)] 316 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))] 317 [Localizable (true)] 318 [TypeConverter (typeof (ImageIndexConverter))] 319 [RefreshProperties (RefreshProperties.Repaint)] 320 public int ImageIndex { 321 get { 322 if (ImageList == null) { 323 return -1; 324 } 325 326 if (image_index >= image_list.Images.Count) { 327 return image_list.Images.Count - 1; 328 } 329 330 return image_index; 331 } 332 set { 333 334 if (value < -1) 335 throw new ArgumentException (); 336 337 if (this.image_index != value) { 338 this.image_index = value; 339 this.image = null; 340 this.image_key = string.Empty; 341 Invalidate (); 342 } 343 } 344 } 345 346 [Localizable (true)] 347 [DefaultValue ("")] 348 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))] 349 [RefreshProperties (RefreshProperties.Repaint)] 350 [TypeConverter (typeof (ImageKeyConverter))] 351 public string ImageKey { 352 get { return this.image_key; } 353 set { 354 if (this.image_key != value) { 355 this.image = null; 356 this.image_index = -1; 357 this.image_key = value; 358 this.Invalidate (); 359 } 360 } 361 } 362 363 [DefaultValue(null)] 364 [RefreshProperties (RefreshProperties.Repaint)] 365 public ImageList ImageList { 366 get { return image_list;} 367 set { 368 if (image_list == value) 369 return; 370 371 image_list = value; 372 373 if (image_list != null && image_index !=-1) 374 Image = null; 375 376 Invalidate (); 377 } 378 } 379 380 [Browsable(false)] 381 [EditorBrowsable(EditorBrowsableState.Never)] 382 public new ImeMode ImeMode { 383 get { return base.ImeMode; } 384 set { base.ImeMode = value; } 385 } 386 InternalGetPreferredSize(Size proposed)387 internal virtual Size InternalGetPreferredSize (Size proposed) 388 { 389 Size size; 390 391 if (Text == string.Empty) { 392 size = new Size (0, Font.Height); 393 } else { 394 size = Size.Ceiling (TextRenderer.MeasureString (Text, Font, req_witdthsize, string_format)); 395 size.Width += 3; 396 } 397 398 size.Width += Padding.Horizontal; 399 size.Height += Padding.Vertical; 400 401 if (!use_compatible_text_rendering) 402 return size; 403 404 if (border_style == BorderStyle.None) 405 size.Height += 3; 406 else 407 size.Height += 6; 408 409 return size; 410 } 411 GetPreferredSize(Size proposedSize)412 public override Size GetPreferredSize (Size proposedSize) 413 { 414 return InternalGetPreferredSize (proposedSize); 415 } 416 417 [Browsable(false)] 418 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)] 419 [EditorBrowsable(EditorBrowsableState.Advanced)] 420 public virtual int PreferredHeight { 421 get { return InternalGetPreferredSize (Size.Empty).Height; } 422 } 423 424 [Browsable(false)] 425 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)] 426 [EditorBrowsable(EditorBrowsableState.Advanced)] 427 public virtual int PreferredWidth { 428 get { return InternalGetPreferredSize (Size.Empty).Width; } 429 } 430 431 [Obsolete ("This property has been deprecated. Use BackColor instead.")] 432 protected virtual bool RenderTransparent { 433 get { return render_transparent; } 434 set { render_transparent = value;} 435 } 436 437 [Browsable(false)] 438 [DefaultValue(false)] 439 [EditorBrowsable(EditorBrowsableState.Never)] 440 public new bool TabStop { 441 get { return base.TabStop; } 442 set { base.TabStop = value; } 443 } 444 445 [DefaultValue(ContentAlignment.TopLeft)] 446 [Localizable(true)] 447 public virtual ContentAlignment TextAlign { 448 get { return text_align; } 449 450 set { 451 if (!Enum.IsDefined (typeof (ContentAlignment), value)) 452 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for ContentAlignment", value)); 453 454 if (text_align != value) { 455 text_align = value; 456 switch (value) { 457 case ContentAlignment.BottomLeft: 458 string_format.LineAlignment = StringAlignment.Far; 459 string_format.Alignment = StringAlignment.Near; 460 break; 461 case ContentAlignment.BottomCenter: 462 string_format.LineAlignment = StringAlignment.Far; 463 string_format.Alignment = StringAlignment.Center; 464 break; 465 case ContentAlignment.BottomRight: 466 string_format.LineAlignment = StringAlignment.Far; 467 string_format.Alignment = StringAlignment.Far; 468 break; 469 case ContentAlignment.TopLeft: 470 string_format.LineAlignment = StringAlignment.Near; 471 string_format.Alignment = StringAlignment.Near; 472 break; 473 case ContentAlignment.TopCenter: 474 string_format.LineAlignment = StringAlignment.Near; 475 string_format.Alignment = StringAlignment.Center; 476 break; 477 case ContentAlignment.TopRight: 478 string_format.LineAlignment = StringAlignment.Near; 479 string_format.Alignment = StringAlignment.Far; 480 break; 481 case ContentAlignment.MiddleLeft: 482 string_format.LineAlignment = StringAlignment.Center; 483 string_format.Alignment = StringAlignment.Near; 484 break; 485 case ContentAlignment.MiddleRight: 486 string_format.LineAlignment = StringAlignment.Center; 487 string_format.Alignment = StringAlignment.Far; 488 break; 489 case ContentAlignment.MiddleCenter: 490 string_format.LineAlignment = StringAlignment.Center; 491 string_format.Alignment = StringAlignment.Center; 492 break; 493 default: 494 break; 495 } 496 497 OnTextAlignChanged (EventArgs.Empty); 498 Invalidate (); 499 } 500 } 501 } 502 503 [DefaultValue(true)] 504 public bool UseMnemonic { 505 get { return use_mnemonic; } 506 set { 507 if (use_mnemonic != value) { 508 use_mnemonic = value; 509 SetUseMnemonic (use_mnemonic); 510 Invalidate (); 511 } 512 } 513 } 514 515 #endregion 516 517 #region Public Methods 518 CalcImageRenderBounds(Image image, Rectangle r, ContentAlignment align)519 protected Rectangle CalcImageRenderBounds (Image image, Rectangle r, ContentAlignment align) 520 { 521 Rectangle rcImageClip = r; 522 rcImageClip.Inflate (-2,-2); 523 524 int X = r.X; 525 int Y = r.Y; 526 527 if (align == ContentAlignment.TopCenter || 528 align == ContentAlignment.MiddleCenter || 529 align == ContentAlignment.BottomCenter) { 530 X += (r.Width - image.Width) / 2; 531 } else if (align == ContentAlignment.TopRight || 532 align == ContentAlignment.MiddleRight|| 533 align == ContentAlignment.BottomRight) { 534 X += (r.Width - image.Width); 535 } 536 537 if( align == ContentAlignment.BottomCenter || 538 align == ContentAlignment.BottomLeft || 539 align == ContentAlignment.BottomRight) { 540 Y += r.Height - image.Height; 541 } else if(align == ContentAlignment.MiddleCenter || 542 align == ContentAlignment.MiddleLeft || 543 align == ContentAlignment.MiddleRight) { 544 Y += (r.Height - image.Height) / 2; 545 } 546 547 rcImageClip.X = X; 548 rcImageClip.Y = Y; 549 rcImageClip.Width = image.Width; 550 rcImageClip.Height = image.Height; 551 552 return rcImageClip; 553 } 554 CreateAccessibilityInstance()555 protected override AccessibleObject CreateAccessibilityInstance () 556 { 557 return base.CreateAccessibilityInstance (); 558 } 559 Dispose(bool disposing)560 protected override void Dispose(bool disposing) 561 { 562 base.Dispose (disposing); 563 564 if (disposing) 565 string_format.Dispose (); 566 } 567 DrawImage(Graphics g, Image image, Rectangle r, ContentAlignment align)568 protected internal void DrawImage (Graphics g, Image image, Rectangle r, ContentAlignment align) 569 { 570 if (image == null || g == null) 571 return; 572 573 Rectangle rcImageClip = CalcImageRenderBounds (image, r, align); 574 575 if (Enabled) 576 g.DrawImage (image, rcImageClip.X, rcImageClip.Y, rcImageClip.Width, rcImageClip.Height); 577 else 578 ControlPaint.DrawImageDisabled (g, image, rcImageClip.X, rcImageClip.Y, BackColor); 579 } 580 OnEnabledChanged(EventArgs e)581 protected override void OnEnabledChanged (EventArgs e) 582 { 583 base.OnEnabledChanged (e); 584 } 585 OnFontChanged(EventArgs e)586 protected override void OnFontChanged (EventArgs e) 587 { 588 base.OnFontChanged (e); 589 if (autosize) 590 CalcAutoSize(); 591 Invalidate (); 592 } 593 OnPaddingChanged(EventArgs e)594 protected override void OnPaddingChanged (EventArgs e) 595 { 596 base.OnPaddingChanged (e); 597 } 598 OnPaint(PaintEventArgs e)599 protected override void OnPaint (PaintEventArgs e) 600 { 601 ThemeElements.LabelPainter.Draw (e.Graphics, ClientRectangle, this); 602 base.OnPaint(e); 603 } 604 OnParentChanged(EventArgs e)605 protected override void OnParentChanged (EventArgs e) 606 { 607 base.OnParentChanged (e); 608 } 609 OnRightToLeftChanged(EventArgs e)610 protected override void OnRightToLeftChanged (EventArgs e) 611 { 612 base.OnRightToLeftChanged (e); 613 } 614 OnTextAlignChanged(EventArgs e)615 protected virtual void OnTextAlignChanged (EventArgs e) 616 { 617 EventHandler eh = (EventHandler)(Events [TextAlignChangedEvent]); 618 if (eh != null) 619 eh (this, e); 620 } 621 OnTextChanged(EventArgs e)622 protected override void OnTextChanged (EventArgs e) 623 { 624 base.OnTextChanged (e); 625 if (autosize) 626 CalcAutoSize (); 627 Invalidate (); 628 } 629 OnVisibleChanged(EventArgs e)630 protected override void OnVisibleChanged (EventArgs e) 631 { 632 base.OnVisibleChanged (e); 633 } 634 ProcessMnemonic(char charCode)635 protected override bool ProcessMnemonic (char charCode) 636 { 637 if (IsMnemonic (charCode, Text)) { 638 // Select item next in line in tab order 639 if (this.Parent != null) 640 Parent.SelectNextControl(this, true, false, false, false); 641 return true; 642 } 643 644 return base.ProcessMnemonic (charCode); 645 } 646 SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)647 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified) 648 { 649 base.SetBoundsCore (x, y, width, height, specified); 650 } 651 ToString()652 public override string ToString() 653 { 654 return base.ToString () + ", Text: " + Text; 655 } 656 WndProc(ref Message m)657 protected override void WndProc (ref Message m) 658 { 659 switch ((Msg) m.Msg) { 660 case Msg.WM_DRAWITEM: 661 m.Result = (IntPtr)1; 662 break; 663 default: 664 base.WndProc (ref m); 665 break; 666 } 667 } 668 669 #endregion Public Methods 670 671 #region Private Methods 672 CalcAutoSize()673 private void CalcAutoSize () 674 { 675 if (!AutoSize) 676 return; 677 678 Size s = InternalGetPreferredSize (Size.Empty); 679 680 SetBounds (Left, Top, s.Width, s.Height, BoundsSpecified.Size); 681 } 682 OnHandleCreatedLB(Object o, EventArgs e)683 private void OnHandleCreatedLB (Object o, EventArgs e) 684 { 685 if (autosize) 686 CalcAutoSize (); 687 } 688 SetUseMnemonic(bool use)689 private void SetUseMnemonic (bool use) 690 { 691 if (use) 692 string_format.HotkeyPrefix = HotkeyPrefix.Show; 693 else 694 string_format.HotkeyPrefix = HotkeyPrefix.None; 695 } 696 697 #endregion Private Methods 698 [DefaultValue (false)] 699 public bool UseCompatibleTextRendering { 700 get { return use_compatible_text_rendering; } 701 set { use_compatible_text_rendering = value; } 702 } 703 704 [SettingsBindable (true)] 705 [Editor ("System.ComponentModel.Design.MultilineStringEditor, " + Consts.AssemblySystem_Design, 706 typeof (System.Drawing.Design.UITypeEditor))] 707 public override string Text { 708 get { return base.Text; } 709 set { base.Text = value; } 710 } 711 OnMouseEnter(EventArgs e)712 protected override void OnMouseEnter (EventArgs e) 713 { 714 base.OnMouseEnter (e); 715 } 716 OnMouseLeave(EventArgs e)717 protected override void OnMouseLeave (EventArgs e) 718 { 719 base.OnMouseLeave (e); 720 } 721 OnHandleDestroyed(EventArgs e)722 protected override void OnHandleDestroyed (EventArgs e) 723 { 724 base.OnHandleDestroyed (e); 725 } 726 } 727 } 728