diff --git a/WIndows.Forms/Extenders/VistaControlExtender.cs b/WIndows.Forms/Extenders/VistaControlExtender.cs
index 28c4ae84..1b197069 100644
--- a/WIndows.Forms/Extenders/VistaControlExtender.cs
+++ b/WIndows.Forms/Extenders/VistaControlExtender.cs
@@ -1,58 +1,129 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
-using System.Runtime.InteropServices;
+using System.Linq;
using System.Windows.Forms;
using Vanara.Extensions;
-using static Vanara.PInvoke.ComCtl32;
using static Vanara.PInvoke.User32;
namespace Vanara.Windows.Forms
{
+ /// Extends standard WinForms controls with post-Vista capabilities.
+ ///
+ ///
[ProvideProperty(ShowShield, typeof(ButtonBase))]
[ProvideProperty(CueBanner, typeof(ComboBox))]
[ProvideProperty(MinVisibleItems, typeof(ComboBox))]
- [ProvideProperty(CueBanner, typeof(TextBox))]
- public sealed class VistaControlExtender : Component, IExtenderProvider
+ //[ProvideProperty(CueBanner, typeof(TextBox))]
+ public sealed class VistaControlExtender : Component, IExtenderProvider, ISupportInitialize
{
internal const string CueBanner = "CueBanner";
internal const string MinVisibleItems = "MinVisibleItems";
internal const string ShowShield = "ShowShield";
- private readonly Dictionary> bag = new Dictionary>();
+ private readonly Dictionary setter)>> bag = new Dictionary setter)>>();
+ private readonly Container components = new Container();
+
+ /// Initializes a new instance of the class.
+ public VistaControlExtender() { }
+
+ /// Initializes a new instance of the class.
+ /// The container.
+ public VistaControlExtender(IContainer container) => container.Add(this);
private static bool IsMinVista { get; } = Environment.OSVersion.Version.Major >= 6;
- [DisplayName(ShowShield)]
- [DefaultValue(false)]
- [Category("Appearance")]
- [Description("Indicates whether a shield is shown on the button to indicate that elevated permissions are required to perform the action of the button.")]
- public bool GetShowShield(ButtonBase btn) => GetValue(btn, ShowShield);
-
- public void SetShowShield(ButtonBase btn, bool value)
- {
- if (SetValue(btn, ShowShield, value))
- btn.SetElevationRequiredState(value);
- }
-
+ /// Gets the text that is displayed as a prompt for an unselected .
+ /// The instance.
+ /// The cue text to display.
[DisplayName(CueBanner), DefaultValue(null), Category("Appearance")]
[Description("Text that is displayed as a prompt for an unselected ComboBox.")]
- public string GetCueBanner(ComboBox comboBox) => GetValue(comboBox, CueBanner);
+ public string GetCueBanner(ComboBox comboBox) => GetValue(comboBox, CueBanner, out _);
- public void SetCueBanner(ComboBox comboBox, string value)
- {
- if (SetValue(comboBox, CueBanner, value))
- comboBox.SetCueBanner(value);
- }
+ /// Sets the text that is displayed as a prompt for an unselected .
+ /// The instance.
+ /// The cue text to display.
+ public void SetCueBanner(ComboBox comboBox, string value) => SetValue(comboBox, CueBanner, value, SetCueBannerValue);
+ /// Gets the minimum number of visible items in the drop-down list of a .
+ /// The instance.
+ /// The minimum number of visible items in the drop-down list.
[DisplayName(MinVisibleItems), DefaultValue(30), Category("Appearance")]
[Description("The minimum number of visible items in the drop-down list of a combo box.")]
- public int GetMinVisibleItems(ComboBox comboBox) => GetValue(comboBox, MinVisibleItems, SendMessage(comboBox.Handle, (uint)ComboBoxMessage.CB_SETMINVISIBLE).ToInt32());
+ public int GetMinVisibleItems(ComboBox comboBox) => GetValue(comboBox, MinVisibleItems, out _, comboBox.SendMessage((uint)ComboBoxMessage.CB_SETMINVISIBLE).ToInt32());
- public void SetMinVisibleItems(ComboBox comboBox, int value)
+ /// Sets the minimum number of visible items in the drop-down list of a .
+ /// The instance.
+ /// The minimum number of visible items in the drop-down list.
+ public void SetMinVisibleItems(ComboBox comboBox, int value) => SetValue(comboBox, MinVisibleItems, value, SetMinVisibleItemsValue);
+
+ ///
+ /// Gets a value which indicates whether a shield is shown on the button to indicate that elevated permissions are required to
+ /// perform the action of the button.
+ ///
+ /// The Button instance.
+ /// if the shield should be shown; otherwise.
+ [DisplayName(ShowShield), DefaultValue(false), Category("Appearance")]
+ [Description("Indicates whether a shield is shown on the button to indicate that elevated permissions are required to perform the action of the button.")]
+ public bool GetShowShield(ButtonBase btn) => GetValue(btn, ShowShield, out _);
+
+ ///
+ /// Sets a value which indicates whether a shield is shown on the button to indicate that elevated permissions are required to
+ /// perform the action of the button.
+ ///
+ /// The Button instance.
+ /// if the shield should be shown; otherwise.
+ public void SetShowShield(ButtonBase btn, bool value) => SetValue(btn, ShowShield, value, SetShowShieldValue);
+
+ void ISupportInitialize.BeginInit()
{
- if (SetValue(comboBox, MinVisibleItems, value) && IsMinVista && comboBox.IsHandleCreated)
- SendMessage(comboBox.Handle, (uint)ComboBoxMessage.CB_SETMINVISIBLE, (IntPtr)value);
+ }
+
+ bool IExtenderProvider.CanExtend(object extendee) => extendee is ComboBox || (extendee is ButtonBase && extendee.GetType().GetProperty(ShowShield) is null);
+
+ void ISupportInitialize.EndInit()
+ {
+ if (!DesignMode)
+ {
+ foreach (var key in bag.Keys.OfType())
+ key.HandleCreated += OnComponentHandleCreated;
+ }
+ }
+
+ ///
+ /// Releases the unmanaged resources used by the and optionally releases the managed resources.
+ ///
+ ///
+ /// to release both managed and unmanaged resources; to release only unmanaged resources.
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ foreach (var key in bag.Keys.OfType())
+ try { key.HandleCreated -= OnComponentHandleCreated; } catch { }
+ components?.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ private static void SetCueBannerValue(Control comboBox, object value)
+ {
+ (comboBox as ComboBox)?.SetCueBanner(value?.ToString());
+ comboBox.Invalidate();
+ }
+
+ private static void SetMinVisibleItemsValue(Control comboBox, object value)
+ {
+ if (!IsMinVista) return;
+ comboBox.SendMessage((uint)ComboBoxMessage.CB_SETMINVISIBLE, (IntPtr)value);
+ comboBox.Invalidate();
+ }
+
+ private static void SetShowShieldValue(Control btn, object value)
+ {
+ (btn as ButtonBase)?.SetElevationRequiredState((bool)value);
+ btn.Invalidate();
}
/*[DisplayName(CueBanner), DefaultValue(null), Category("Appearance")]
@@ -65,20 +136,30 @@ namespace Vanara.Windows.Forms
textBox.SetCueBanner(value);
}*/
- bool IExtenderProvider.CanExtend(object extendee) { return extendee is Component; }
-
- private T GetValue(Component comp, string propName, T defValue = default)
+ private T GetValue(Control comp, string propName, out Action setter, T defValue = default)
{
- try { return (T)bag[comp][propName]; } catch { }
+ if (bag.TryGetValue(comp, out var props) && props.TryGetValue(propName, out var value))
+ {
+ setter = value.setter;
+ return (T)value.value;
+ }
+ setter = null;
return defValue;
}
- private bool SetValue(Component comp, string propName, T value)
+ private void OnComponentHandleCreated(object sender, EventArgs e)
{
- if (Equals(value, GetValue(comp, propName))) return false;
+ foreach (var kv in bag.Where(kv => ReferenceEquals(kv.Key, sender)))
+ foreach (var (value, setter) in kv.Value.Values)
+ setter?.Invoke(sender as Control, value);
+ }
+
+ private bool SetValue(Control comp, string propName, T value, Action setter)
+ {
+ if (Equals(value, GetValue(comp, propName, out _))) return false;
if (!bag.ContainsKey(comp))
- bag.Add(comp, new Dictionary());
- bag[comp][propName] = value;
+ bag.Add(comp, new Dictionary setter)>());
+ bag[comp][propName] = (value, setter);
return true;
}
}