using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; using System.Windows.Forms.Design; using Microsoft.Win32; namespace Unclassified.UI { /// [Designer(typeof(InfoLabelDesigner))] [DefaultEvent("Click")] public class InfoLabel : UserControl { #region Private fields private bool useBorder = false; private Color borderColor; private Pen borderColorPen; private Brush backColorBrush; private Color hoverBackColor; private Color hoverBorderColor; private Pen hoverBorderColorPen; private Brush hoverBackColorBrush; private Color hoverForeColor; private Brush hoverForeColorBrush; private bool hovering = false; private bool supportHovering = false; private ContextMenu contextMenu = null; private ContextMenuStrip contextMenuStrip = null; #endregion Private fields #region Constructors public InfoLabel() { InitializeComponent(); BackColor = SystemColors.Info; ForeColor = SystemColors.InfoText; BorderColor = SystemColors.ControlDark; HoverBackColor = SystemColors.Highlight; HoverForeColor = SystemColors.HighlightText; HoverBorderColor = SystemColors.ControlDark; } #endregion Constructors #region Designer stuff private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; private System.Windows.Forms.PictureBox pictureBox1; private System.Windows.Forms.Label label1; private System.ComponentModel.IContainer components = null; protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } private void InitializeComponent() { this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); this.pictureBox1 = new System.Windows.Forms.PictureBox(); this.label1 = new System.Windows.Forms.Label(); this.flowLayoutPanel1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize) (this.pictureBox1)).BeginInit(); this.SuspendLayout(); // // flowLayoutPanel1 // this.flowLayoutPanel1.AutoSize = true; this.flowLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.flowLayoutPanel1.BackColor = System.Drawing.Color.Transparent; this.flowLayoutPanel1.Controls.Add(this.pictureBox1); this.flowLayoutPanel1.Controls.Add(this.label1); this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Top; this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; this.flowLayoutPanel1.Location = new System.Drawing.Point(0, 0); this.flowLayoutPanel1.Name = "flowLayoutPanel1"; this.flowLayoutPanel1.Padding = new System.Windows.Forms.Padding(3); this.flowLayoutPanel1.Size = new System.Drawing.Size(279, 34); this.flowLayoutPanel1.TabIndex = 0; this.flowLayoutPanel1.MouseLeave += new System.EventHandler(this.flowLayoutPanel1_MouseLeave); this.flowLayoutPanel1.Click += new System.EventHandler(this.flowLayoutPanel1_Click); this.flowLayoutPanel1.Resize += new System.EventHandler(this.flowLayoutPanel1_Resize); this.flowLayoutPanel1.MouseEnter += new System.EventHandler(this.flowLayoutPanel1_MouseEnter); // // pictureBox1 // this.pictureBox1.BackColor = System.Drawing.Color.Transparent; this.flowLayoutPanel1.SetFlowBreak(this.pictureBox1, true); this.pictureBox1.Location = new System.Drawing.Point(3, 3); this.pictureBox1.Margin = new System.Windows.Forms.Padding(1, 0, 2, 0); this.pictureBox1.Name = "pictureBox1"; this.pictureBox1.Size = new System.Drawing.Size(16, 16); this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; this.pictureBox1.TabIndex = 0; this.pictureBox1.TabStop = false; this.pictureBox1.Visible = false; this.pictureBox1.MouseLeave += new System.EventHandler(this.flowLayoutPanel1_MouseLeave); this.pictureBox1.Click += new System.EventHandler(this.flowLayoutPanel1_Click); this.pictureBox1.MouseEnter += new System.EventHandler(this.flowLayoutPanel1_MouseEnter); // // label1 // this.label1.AutoSize = true; this.label1.BackColor = System.Drawing.Color.Transparent; this.label1.Location = new System.Drawing.Point(23, 4); this.label1.Margin = new System.Windows.Forms.Padding(0, 1, 0, 1); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(247, 26); this.label1.TabIndex = 1; this.label1.Text = "label1"; this.label1.UseMnemonic = false; this.label1.MouseLeave += new System.EventHandler(this.flowLayoutPanel1_MouseLeave); this.label1.Click += new System.EventHandler(this.flowLayoutPanel1_Click); this.label1.MouseEnter += new System.EventHandler(this.flowLayoutPanel1_MouseEnter); // // InfoLabel // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.flowLayoutPanel1); this.DoubleBuffered = true; this.Name = "InfoLabel"; this.Size = new System.Drawing.Size(279, 80); this.Enter += new System.EventHandler(this.InfoLabel_Enter); this.Leave += new System.EventHandler(this.InfoLabel_Leave); this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.InfoLabel_KeyDown); this.flowLayoutPanel1.ResumeLayout(false); this.flowLayoutPanel1.PerformLayout(); ((System.ComponentModel.ISupportInitialize) (this.pictureBox1)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } #endregion Designer stuff #region Old properties public override Color BackColor { get { return base.BackColor; } set { base.BackColor = value; backColorBrush = new SolidBrush(value); } } [Browsable(false)] public override Image BackgroundImage { get { return base.BackgroundImage; } set { base.BackgroundImage = null; } } [Browsable(false)] public override ImageLayout BackgroundImageLayout { get { return base.BackgroundImageLayout; } set { base.BackgroundImageLayout = ImageLayout.None; } } [Browsable(false)] public new BorderStyle BorderStyle { get { return BorderStyle.None; } } public override AnchorStyles Anchor { get { return base.Anchor; } set { if ((value & AnchorStyles.Top) != 0 && (value & AnchorStyles.Bottom) != 0) throw new ArgumentException(); base.Anchor = value; } } [Browsable(false)] public override bool AutoScroll { get { return base.AutoScroll; } set { base.AutoScroll = false; } } [Browsable(false)] public override bool AutoSize { get { return base.AutoSize; } set { base.AutoSize = false; } } public override DockStyle Dock { get { return base.Dock; } set { if (value == DockStyle.Fill || value == DockStyle.Left || value == DockStyle.Right) throw new ArgumentException(); base.Dock = value; } } // This must be named different from "Text" because the designer won't // store that property persistently and reset it every time the project // is rebuilt. //[Category("Appearance")] //[Browsable(false)] //public string Text2 //{ // get // { // return label1.Text; // } // set // { // label1.Text = value; // } //} [Browsable(true)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public override string Text { get { return label1.Text; } set { label1.Text = value; } } public override ContextMenu ContextMenu { get { return contextMenu; } set { contextMenu = value; } } public override ContextMenuStrip ContextMenuStrip { get { return contextMenuStrip; } set { contextMenuStrip = value; } } #endregion Old properties #region New properties [Category("Appearance")] public Color BorderColor { get { return borderColor; } set { borderColor = value; borderColorPen = new Pen(borderColor); Invalidate(); } } [Category("Appearance")] public Color HoverBorderColor { get { return hoverBorderColor; } set { hoverBorderColor = value; hoverBorderColorPen = new Pen(hoverBorderColor); Invalidate(); } } [Category("Appearance")] public bool UseBorder { get { return useBorder; } set { useBorder = value; flowLayoutPanel1.Padding = new Padding(useBorder ? 3 : 2); Invalidate(); } } [Category("Appearance")] public Color HoverBackColor { get { return hoverBackColor; } set { hoverBackColor = value; hoverBackColorBrush = new SolidBrush(value); Invalidate(); } } [Category("Appearance")] public Color HoverForeColor { get { return hoverForeColor; } set { hoverForeColor = value; hoverForeColorBrush = new SolidBrush(value); Invalidate(); } } [Category("Appearance")] public Image IconImage { get { return pictureBox1.Image; } set { pictureBox1.Image = value; pictureBox1.Visible = value != null; } } [Category("Behavior")] public bool SupportHovering { get { return supportHovering; } set { supportHovering = value; UpdateHovering(); Invalidate(); } } #endregion New properties #region New event handlers protected override void OnSizeChanged(EventArgs e) { Invalidate(); base.OnSizeChanged(e); } private void flowLayoutPanel1_Resize(object sender, EventArgs e) { UpdateSize(); } private void flowLayoutPanel1_MouseEnter(object sender, EventArgs e) { hovering = true; UpdateHovering(); Invalidate(); } private void flowLayoutPanel1_MouseLeave(object sender, EventArgs e) { hovering = false; UpdateHovering(); Invalidate(); } protected override void OnPaintBackground(PaintEventArgs e) { base.OnPaintBackground(e); if (useBorder) { if (supportHovering && hovering) { e.Graphics.FillRectangle(hoverBackColorBrush, 1, 1, Width - 2, Height - 2); e.Graphics.DrawRectangle(hoverBorderColorPen, 0, 0, Width - 1, Height - 1); } else { //e.Graphics.FillRectangle(backColorBrush, 1, 1, Width - 2, Height - 2); e.Graphics.DrawRectangle(borderColorPen, 0, 0, Width - 1, Height - 1); } } else { if (supportHovering && hovering) { e.Graphics.FillRectangle(hoverBackColorBrush, 0, 0, Width, Height); } else { //e.Graphics.FillRectangle(backColorBrush, 0, 0, Width, Height); } } } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); if (Focused || FindForm() != null && FindForm().ActiveControl == this) // Focused alone doesn't work when re-activating the window { e.Graphics.DrawRectangle(new Pen(new HatchBrush(HatchStyle.Percent50, label1.ForeColor, Color.Empty)), 0, 0, Width - 1, Height - 1); } } #endregion New event handlers #region Other private methods private void UpdateSize() { int oldHeight = Height; Height = flowLayoutPanel1.Height; if (Height != oldHeight) Invalidate(); } private void UpdateHovering() { if (supportHovering && hovering) { label1.ForeColor = HoverForeColor; Cursor = HandCursor; } else { label1.ForeColor = Color.Empty; Cursor = Cursors.Default; } } #endregion Other private methods #region Public events public new event EventHandler Click; private void flowLayoutPanel1_Click(object sender, EventArgs e) { if (ContextMenu != null) { ContextMenu.Show(this, new Point(0, Height - (useBorder ? 1 : 0))); } else if (ContextMenuStrip != null) { ContextMenuStrip.Show(this, new Point(0, Height - (useBorder ? 1 : 0))); } else { if (Click != null) Click(this, EventArgs.Empty); } } private void InfoLabel_Enter(object sender, EventArgs e) { Invalidate(); } private void InfoLabel_Leave(object sender, EventArgs e) { Invalidate(); } private void InfoLabel_KeyDown(object sender, KeyEventArgs e) { if ((e.KeyCode == Keys.Enter || e.KeyCode == Keys.Space) && !e.Alt && !e.Control && !e.Shift) { flowLayoutPanel1_Click(this, EventArgs.Empty); e.Handled = true; e.SuppressKeyPress = true; } } #endregion Public events #region WinAPI stuff // This comes from class Unclassified.WinApi [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern IntPtr LoadCursorFromFile(string path); /// /// Gets the system's hand mouse cursor, used for hyperlinks. /// The .NET framework only gives its internal cursor but not the one that the user has set in their profile. /// private Cursor HandCursor { get { RegistryKey cursorsKey = Registry.CurrentUser.OpenSubKey(@"Control Panel\Cursors"); if (cursorsKey != null) { object o = cursorsKey.GetValue("Hand"); if (o is string) { IntPtr cursorHandle = WinApi.LoadCursorFromFile((string) o); return new Cursor(cursorHandle); } } return Cursors.Hand; } } } #endregion WinAPI stuff } public class InfoLabelDesigner : ControlDesigner { public override SelectionRules SelectionRules { get { return base.SelectionRules & ~(SelectionRules.TopSizeable | SelectionRules.BottomSizeable); } } } }