mirror of https://github.com/dahall/Vanara.git
315 lines
13 KiB
C#
315 lines
13 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Security.Permissions;
|
|
using System.Windows.Forms;
|
|
using Vanara.PInvoke;
|
|
|
|
namespace Vanara.Windows.Shell
|
|
{
|
|
/// <summary>Provides access to the functionality of the taskbar button.</summary>
|
|
/// <seealso cref="System.ComponentModel.Component"/>
|
|
[ProvideProperty("AppID", typeof(Form))]
|
|
[ProvideProperty("TaskbarButtonTooltip", typeof(Form))]
|
|
[ProvideProperty("TaskbarButtonOverlay", typeof(Form))]
|
|
[ProvideProperty("TaskbarButtonOverlayTooltip", typeof(Form))]
|
|
[ProvideProperty("TaskbarButtonProgressState", typeof(Form))]
|
|
[ProvideProperty("TaskbarButtonProgressValue", typeof(Form))]
|
|
[ProvideProperty("JumpList", typeof(Form))]
|
|
[ProvideProperty("TaskbarButtonThumbnails", typeof(Form))]
|
|
public class TaskbarButton : ExtenderProviderBase<Form>, INotifyPropertyChanged
|
|
{
|
|
private const string category = "Taskbar Button";
|
|
|
|
static TaskbarButton() => Application.AddMessageFilter(new ThumbButtonMessageFilter());
|
|
|
|
/// <summary>Initializes a new instance of the <see cref="TaskbarButton"/> class.</summary>
|
|
public TaskbarButton()
|
|
{
|
|
TaskbarButtonCreated += OnTaskbarButtonCreated;
|
|
ThumbnailButtonClick += OnThumbnailButtonClick;
|
|
}
|
|
|
|
/// <summary>Initializes a new instance of the <see cref="TaskbarButton"/> class.</summary>
|
|
/// <param name="container">The container of this component.</param>
|
|
/// <exception cref="System.ArgumentNullException">container</exception>
|
|
public TaskbarButton(IContainer container) : this()
|
|
{
|
|
if (container is null)
|
|
throw new ArgumentNullException(nameof(container));
|
|
container.Add(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when the system reports a taskbar button has been created. The first parameter will contain the HWND of the window for
|
|
/// which the button was created.
|
|
/// </summary>
|
|
public static event Action<HWND> TaskbarButtonCreated;
|
|
|
|
/// <summary>
|
|
/// Occurs when the system reports a thumbnail button has been clicked. The first parameter contains the HWND of the window shown by
|
|
/// the thumbnail and the second contains the Command ID of the button that was clicked.
|
|
/// </summary>
|
|
public static event Action<HWND, int> ThumbnailButtonClick;
|
|
|
|
/// <summary>Occurs when a property has changed.</summary>
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
|
|
/// <summary>Gets a value indicating whether the taskbar button has been created.</summary>
|
|
/// <value><see langword="true"/> if the taskbar button was created; otherwise, <see langword="false"/>.</value>
|
|
[Browsable(false)]
|
|
public bool IsTaskbarButtonCreated { get; internal set; } = false;
|
|
|
|
/// <summary>Signals the object that initialization is starting.</summary>
|
|
public override void BeginInit()
|
|
{
|
|
base.BeginInit();
|
|
if (Container is Form f && f.ShowInTaskbar)
|
|
TaskbarList.ActivateTaskbarItem(f.Handle);
|
|
}
|
|
|
|
/// <summary>Gets the application identifier.</summary>
|
|
/// <param name="form">The form.</param>
|
|
/// <returns>The application identifier.</returns>
|
|
[Category(category), DisplayName("AppID"), DefaultValue(null)]
|
|
[Description("Gets or sets the application identifier.")]
|
|
public string GetAppID(Form form) => GetPropertyValue<string>(form);
|
|
|
|
/// <summary>Gets the jumplist to display on this taskbar button.</summary>
|
|
/// <param name="form">The form.</param>
|
|
/// <returns>The jumplist.</returns>
|
|
[Category(category), DisplayName("JumpList"), Localizable(true)]
|
|
[Description("Gets the jumplist to display with the taskbar button.")]
|
|
public JumpList GetJumpList(Form form)
|
|
{
|
|
var ret = GetPropertyValue<JumpList>(form);
|
|
if (ret is null)
|
|
{
|
|
ret = new JumpList();
|
|
SetPropertyValue(form, ret, "JumpList");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/// <summary>Gets the overlay icon to dispaly on a taskbar button to indicate application status or a notification to the user.</summary>
|
|
/// <param name="form">The form.</param>
|
|
/// <returns>The overlay icon.</returns>
|
|
[Category(category), DisplayName("TaskbarButtonOverlay"), DefaultValue(null), Localizable(true)]
|
|
[Description("Gets or sets the overlay icon to dispaly on a taskbar button.")]
|
|
public Icon GetTaskbarButtonOverlay(Form form) => GetPropertyValue<Icon>(form);
|
|
|
|
/// <summary>
|
|
/// Gets the overlay tooltip to dispaly on a taskbar button to indicate application status or a notification to the user.
|
|
/// </summary>
|
|
/// <param name="form">The form.</param>
|
|
/// <returns>The overlay tooltip.</returns>
|
|
[Category(category), DisplayName("TaskbarButtonOverlayTooltip"), DefaultValue(null), Localizable(true)]
|
|
[Description("Gets or sets the overlay tooltip to dispaly on a taskbar button.")]
|
|
public string GetTaskbarButtonOverlayTooltip(Form form) => GetPropertyValue<string>(form);
|
|
|
|
/// <summary>Gets the state of the progress indicator displayed on a taskbar button.</summary>
|
|
/// <param name="form">
|
|
/// The window in which the progress of an operation is being shown. This window's associated taskbar button will display the
|
|
/// progress bar.
|
|
/// </param>
|
|
/// <returns>The current state of the progress button.</returns>
|
|
[Category(category), DisplayName("TaskbarButtonProgressState"), DefaultValue(TaskbarButtonProgressState.None)]
|
|
[Description("Gets or sets the state of the progress indicator displayed on a taskbar button.")]
|
|
public TaskbarButtonProgressState GetTaskbarButtonProgressState(Form form) => GetPropertyValue(form, TaskbarButtonProgressState.None);
|
|
|
|
/// <summary>
|
|
/// Displays or updates a progress bar hosted in a taskbar button to show the specific percentage completed of the full operation.
|
|
/// </summary>
|
|
/// <param name="form">The window whose associated taskbar button is being used as a progress indicator.</param>
|
|
/// <returns>The proportion of the operation that has been completed at the time the method is called.</returns>
|
|
[Category(category), DisplayName("TaskbarButtonProgressValue"), DefaultValue(0.0f)]
|
|
[Description("Gets or sets the percentage completion for the progress bar hosted in a taskbar button.")]
|
|
public float GetTaskbarButtonProgressValue(Form form) => GetPropertyValue(form, 0.0f);
|
|
|
|
/// <summary>Gets the taskbar button thumbnails.</summary>
|
|
/// <param name="form">The window owning the taskbar button thumbnails.</param>
|
|
/// <returns>A collection of thumbnails.</returns>
|
|
[Category(category), DisplayName("TaskbarButtonThumbnails")]
|
|
[Description("Gets the list of thumbnails associated with the taskbar button.")]
|
|
public TaskbarButtonThumbnails GetTaskbarButtonThumbnails(Form form)
|
|
{
|
|
var ret = GetPropertyValue<TaskbarButtonThumbnails>(form);
|
|
if (ret is null)
|
|
{
|
|
ret = new TaskbarButtonThumbnails(form);
|
|
SetPropertyValue(form, ret, "TaskbarButtonThumbnails");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/// <summary>Gets the description displayed on the tooltip of the taskbar button.</summary>
|
|
/// <param name="form">The form.</param>
|
|
/// <returns>The description</returns>
|
|
[Category(category), DisplayName("TaskbarButtonTooltip"), DefaultValue(null), Localizable(true)]
|
|
[Description("Gets or sets the description displayed on the tooltip of the taskbar button.")]
|
|
public string GetTaskbarButtonTooltip(Form form) => GetPropertyValue<string>(form);
|
|
|
|
/// <summary>Sets the application identifier.</summary>
|
|
/// <param name="form">The form.</param>
|
|
/// <param name="value">The value.</param>
|
|
public void SetAppID(Form form, string value)
|
|
{
|
|
if (SetPropertyValue(form, value) && IsTaskbarButtonCreated)
|
|
ApplySetting(form, value);
|
|
}
|
|
|
|
/// <summary>Sets the overlay icon to dispaly on a taskbar button to indicate application status or a notification to the user.</summary>
|
|
/// <param name="form">The form.</param>
|
|
/// <param name="value">The overlay icon to apply.</param>
|
|
public void SetTaskbarButtonOverlay(Form form, Icon value)
|
|
{
|
|
if (SetPropertyValue(form, value) && IsTaskbarButtonCreated)
|
|
ApplySetting(form, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the overlay tooltip to dispaly on a taskbar button to indicate application status or a notification to the user.
|
|
/// </summary>
|
|
/// <param name="form">The form.</param>
|
|
/// <param name="value">The overlay tooltip.</param>
|
|
public void SetTaskbarButtonOverlayTooltip(Form form, string value)
|
|
{
|
|
if (SetPropertyValue(form, value) && IsTaskbarButtonCreated)
|
|
ApplySetting(form, value);
|
|
}
|
|
|
|
/// <summary>Sets the type and state of the progress indicator displayed on a taskbar button.</summary>
|
|
/// <param name="form">
|
|
/// The window in which the progress of an operation is being shown. This window's associated taskbar button will display the
|
|
/// progress bar.
|
|
/// </param>
|
|
/// <param name="value">The current state of the progress button. Specify only one of the enum values.</param>
|
|
public void SetTaskbarButtonProgressState(Form form, TaskbarButtonProgressState value)
|
|
{
|
|
if (SetPropertyValue(form, value) && IsTaskbarButtonCreated)
|
|
ApplySetting(form, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Displays or updates a progress bar hosted in a taskbar button to show the specific percentage completed of the full operation.
|
|
/// </summary>
|
|
/// <param name="form">The window whose associated taskbar button is being used as a progress indicator.</param>
|
|
/// <param name="value">
|
|
/// The proportion of the operation that has been completed at the time the method is called. This value must be between 0.0f and
|
|
/// </param>
|
|
public void SetTaskbarButtonProgressValue(Form form, float value)
|
|
{
|
|
if (value < 0f || value > 1.0f)
|
|
throw new ArgumentOutOfRangeException(nameof(value), "Progress value must be a number between 0 and 1, inclusive.");
|
|
if (SetPropertyValue(form, value) && IsTaskbarButtonCreated)
|
|
ApplySetting(form, value);
|
|
}
|
|
|
|
/// <summary>Sets the description displayed on the tooltip of the taskbar button.</summary>
|
|
/// <param name="form">The form.</param>
|
|
/// <param name="value">The description.</param>
|
|
public void SetTaskbarButtonTooltip(Form form, string value)
|
|
{
|
|
if (SetPropertyValue(form, value) && IsTaskbarButtonCreated)
|
|
ApplySetting(form, value);
|
|
}
|
|
|
|
/// <summary>Calls the <see cref="PropertyChanged"/> event.</summary>
|
|
/// <param name="form">The form.</param>
|
|
/// <param name="propName">Name of the changed property.</param>
|
|
protected virtual void OnProperyChanged(Form form, string propName) => PropertyChanged?.Invoke(form, new PropertyChangedEventArgs(propName));
|
|
|
|
private void ApplySetting(Form form, object value, [CallerMemberName] string propName = "")
|
|
{
|
|
if (propName.StartsWith("Set"))
|
|
propName = propName.Remove(0, 3);
|
|
switch (propName)
|
|
{
|
|
case "AppID":
|
|
TaskbarList.SetWindowAppId(form.Handle, (string)value);
|
|
break;
|
|
|
|
case "TaskbarButtonTooltip":
|
|
TaskbarList.SetThumbnailTooltip(form.Handle, (string)value);
|
|
break;
|
|
|
|
case "TaskbarButtonOverlay":
|
|
TaskbarList.SetOverlayIcon(form.Handle, ((Icon)value).Handle, GetTaskbarButtonOverlayTooltip(form));
|
|
break;
|
|
|
|
case "TaskbarButtonOverlayTooltip":
|
|
TaskbarList.SetOverlayIcon(form.Handle, GetTaskbarButtonOverlay(form)?.Handle ?? default, (string)value);
|
|
break;
|
|
|
|
case "TaskbarButtonProgressState":
|
|
TaskbarList.SetProgressState(form.Handle, (TaskbarButtonProgressState)value);
|
|
break;
|
|
|
|
case "TaskbarButtonProgressValue":
|
|
TaskbarList.SetProgressValue(form.Handle, (ulong)(100000 * (float)value), 100000);
|
|
break;
|
|
|
|
case "TaskbarButtonThumbnails":
|
|
GetTaskbarButtonThumbnails(form).ResetToolbar();
|
|
break;
|
|
|
|
case "JumpList":
|
|
GetJumpList(form).ApplySettings(GetAppID(form));
|
|
break;
|
|
|
|
default:
|
|
throw new InvalidOperationException("Unrecognized setting name.");
|
|
}
|
|
OnProperyChanged(form, propName);
|
|
}
|
|
|
|
private void OnTaskbarButtonCreated(HWND hWnd)
|
|
{
|
|
IsTaskbarButtonCreated = true;
|
|
|
|
// Apply any settings for this window
|
|
var form = ExtendedComponents.FirstOrDefault(f => f.Handle == hWnd);
|
|
if (form is null) return;
|
|
foreach (var kv in propHash[form])
|
|
ApplySetting(form, kv.Value, kv.Key);
|
|
}
|
|
|
|
private void OnThumbnailButtonClick(HWND hWnd, int buttonId)
|
|
{
|
|
var form = ExtendedComponents.FirstOrDefault(f => f.Handle == hWnd);
|
|
if (form is null) return;
|
|
var th = GetTaskbarButtonThumbnails(form);
|
|
if (th is null) return;
|
|
if (buttonId >= 0 && buttonId < th.Toolbar.Buttons.Count)
|
|
th.Toolbar.Buttons[buttonId].InvokeClick();
|
|
}
|
|
|
|
#pragma warning disable IDE0051 // Remove unused private members
|
|
private void ResetJumpList(Form form) => propHash[form].Remove("JumpList");
|
|
|
|
private void ResetTaskbarButtonThumbnails(Form form) => propHash[form].Remove("TaskbarButtonThumbnails");
|
|
|
|
private bool ShouldSerializeJumpList(Form form) => GetJumpList(form).Count > 0;
|
|
|
|
private bool ShouldSerializeTaskbarButtonThumbnails(Form form) => GetTaskbarButtonThumbnails(form).Count > 0;
|
|
#pragma warning restore IDE0051 // Remove unused private members
|
|
|
|
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
|
|
private class ThumbButtonMessageFilter : IMessageFilter
|
|
{
|
|
public bool PreFilterMessage(ref Message m)
|
|
{
|
|
if (m.Msg == Shell32.WM_TASKBARBUTTONCREATED)
|
|
TaskbarButtonCreated(m.HWnd);
|
|
else if (m.Msg == (int)User32.WindowMessage.WM_COMMAND && Macros.HIWORD(m.WParam) == Shell32.THBN_CLICKED)
|
|
{
|
|
ThumbnailButtonClick(m.HWnd, Macros.LOWORD(m.WParam));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
} |