using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Drawing; using System.Drawing.Design; using System.Runtime.CompilerServices; using System.Windows.Forms; using static Vanara.PInvoke.Shell32; namespace Vanara.Windows.Shell; /// public enum Visibility : byte { /// The collapsed Collapsed = 2, /// The hidden Hidden = 1, /// The visible Visible = 0 } /// A button in the toolbar associated with thumbnails displayed on a taskbar button. /// [DefaultProperty("Description"), DefaultEvent("Click")] public partial class ThumbnailToolbarButton : INotifyPropertyChanged { internal THUMBBUTTON btn; internal ImageIndexer indexer = new(); private Icon? icon; [MaybeNull] private ThumbnailToolbar parent; private Visibility visibility; /// Initializes a new instance of the class. public ThumbnailToolbarButton() { } /// Occurs when the button is clicked. [Category("Behavior")] public event EventHandler? Click; /// Occurs when a property has changed. public event PropertyChangedEventHandler? PropertyChanged; /// Gets or sets the description displayed as a tooltip for the button. /// The description text. [DefaultValue(null), Category("Appearance")] public string Description { get => btn.szTip; set { btn.szTip = value; btn.dwMask |= THUMBBUTTONMASK.THB_TOOLTIP; OnPropertyChanged(); } } /// Gets or sets a value indicating whether to dismiss the thumbnail when this button is clicked. /// to dismiss when clicked; otherwise, . [DefaultValue(false), Category("Behavior")] public bool DismissWhenClicked { get => GetFlagValue(THUMBBUTTONFLAGS.THBF_DISMISSONCLICK); set => SetFlagValue(THUMBBUTTONFLAGS.THBF_DISMISSONCLICK, value); } /// Gets or sets a value indicating whether to draw the button's border. /// if button border is drawn; otherwise, . [DefaultValue(true), Category("Appearance")] public bool DrawButtonBorder { get => !GetFlagValue(THUMBBUTTONFLAGS.THBF_NOBACKGROUND); set => SetFlagValue(THUMBBUTTONFLAGS.THBF_NOBACKGROUND, !value); } /// Gets or sets the icon shown on the toolbar button. /// The button icon. [Description("ButtonImageDescr"), Localizable(true), Category("Appearance")] [DefaultValue(null)] public Icon? Icon { get => icon; set { if (icon != value) { icon = value; if (icon != null) ImageIndex = -1; UpdateImageInfo(); OnPropertyChanged(); } } } /// Gets or sets the index of the image from . /// The index of the image. /// ImageIndex [TypeConverter(typeof(ImageIndexConverter)), Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor)), Localizable(true), DefaultValue(-1), RefreshProperties(RefreshProperties.Repaint)] [Description("ButtonImageIndexDescr"), Category("Appearance")] public int ImageIndex { get { if (indexer.Index != -1 && Parent?.ImageList != null && indexer.Index >= Parent.ImageList.Images.Count) return Parent.ImageList.Images.Count - 1; return indexer.Index; } set { if (value < -1) throw new ArgumentOutOfRangeException(nameof(ImageIndex)); if (indexer.Index != value) { if (value != -1) icon = null; indexer.Index = value; UpdateImageInfo(); OnPropertyChanged(); } } } /// Gets or sets the image key of the image from . /// The image key value. [TypeConverter(typeof(ImageKeyConverter)), Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor)), Localizable(true), DefaultValue(""), RefreshProperties(RefreshProperties.Repaint)] [Description("ButtonImageIndexDescr"), Category("Appearance")] public string ImageKey { get => indexer.Key ?? ""; set { if (indexer.Key != value) { if (value != null) icon = null; indexer.Key = value; UpdateImageInfo(); OnPropertyChanged(); } } } /// Gets or sets a value indicating whether this button is enabled. /// if this button is enabled; otherwise, . [DefaultValue(true), Category("Behavior")] public bool IsEnabled { get => !GetFlagValue(THUMBBUTTONFLAGS.THBF_DISABLED); set => SetFlagValue(THUMBBUTTONFLAGS.THBF_DISABLED, !value); } /// /// Gets or sets a value indicating whether this button is interactive. If , no pressed button state is /// drawn. This is intended for instances where the button is used in a notification. /// /// if this button is interactive; otherwise, . [DefaultValue(true), Category("Behavior")] public bool IsInteractive { get => !GetFlagValue(THUMBBUTTONFLAGS.THBF_NONINTERACTIVE); set => SetFlagValue(THUMBBUTTONFLAGS.THBF_NONINTERACTIVE, !value); } /// Gets or sets the visibility of the button. /// The button visibility. [DefaultValue(typeof(Visibility), "Visible"), Category("Appearance")] public Visibility Visibility { get => visibility; set { if (visibility != value) { visibility = value; OnPropertyChanged(); } } } internal ThumbnailToolbar Parent { get => parent ?? throw new ArgumentNullException(nameof(Parent), "This property must be set before retrieval."); set { parent = value; indexer.ImageList = value.ImageList; } } internal void InvokeClick() => Click?.Invoke(this, EventArgs.Empty); /// Called when a property has changed. /// Name of the property. protected virtual void OnPropertyChanged([CallerMemberName] string propName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName)); private bool GetFlagValue(THUMBBUTTONFLAGS f) => btn.dwFlags.IsFlagSet(f); private void SetFlagValue(THUMBBUTTONFLAGS f, bool value, [CallerMemberName] string memberName = "") { btn.dwFlags = btn.dwFlags.SetFlags(f, value); btn.dwMask |= THUMBBUTTONMASK.THB_FLAGS; OnPropertyChanged(memberName); } private void UpdateImageInfo() { if (icon == null && indexer.ActualIndex >= 0) { btn.dwMask |= THUMBBUTTONMASK.THB_ICON | THUMBBUTTONMASK.THB_BITMAP; btn.hIcon = IntPtr.Zero; btn.iBitmap = (uint)indexer.ActualIndex; } else { btn.dwMask |= THUMBBUTTONMASK.THB_ICON | THUMBBUTTONMASK.THB_BITMAP; if (icon == null) btn.hIcon = IntPtr.Zero; else btn.hIcon = icon.Handle; btn.iBitmap = 0; } } }