diff --git a/WIndows.Forms/Controls/DisabledItemComboBox.cs b/WIndows.Forms/Controls/DisabledItemComboBox.cs index 0bb2b67e..9a627bc1 100644 --- a/WIndows.Forms/Controls/DisabledItemComboBox.cs +++ b/WIndows.Forms/Controls/DisabledItemComboBox.cs @@ -1,7 +1,6 @@ using System; using System.ComponentModel; using System.Drawing; -using System.Runtime.InteropServices; using System.Windows.Forms; using System.Windows.Forms.VisualStyles; using Vanara.Drawing; @@ -14,9 +13,7 @@ using ComboBoxStyle = System.Windows.Forms.ComboBoxStyle; namespace Vanara.Windows.Forms { - /// - /// Interface that exposes an Enabled property for an item supplied to . - /// + /// Interface that exposes an Enabled property for an item supplied to . public interface IEnableable { /// Gets a value indicating whether an item is enabled. @@ -24,68 +21,51 @@ namespace Vanara.Windows.Forms bool Enabled { get; } } - /// - /// A version of that allows for disabled items. - /// + /// A version of that allows for disabled items. [ToolboxBitmap(typeof(DisabledItemComboBox), "Control")] public class DisabledItemComboBox : ComboBox { private const TextFormatFlags tff = TextFormatFlags.Default | TextFormatFlags.VerticalCenter | TextFormatFlags.SingleLine | TextFormatFlags.NoPadding; + private bool animationsNeedCleanup; private ComboBoxState currentState = ComboBoxState.Normal, newState = ComboBoxState.Normal; private ListBoxNativeWindow dropDownWindow; private readonly VisualStyleRenderer vsr; - /// - /// Initializes a new instance of the class. - /// + /// Initializes a new instance of the class. public DisabledItemComboBox() { SetStyle(/*ControlStyles.Opaque |*/ ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true); DrawMode = DrawMode.OwnerDrawFixed; DropDownStyle = ComboBoxStyle.DropDownList; - if ((Environment.OSVersion.Version.Major >= 6) && VisualStyleRenderer.IsSupported && Application.RenderWithVisualStyles) + if (Environment.OSVersion.Version.Major >= 6 && VisualStyleRenderer.IsSupported && Application.RenderWithVisualStyles) vsr = new VisualStyleRenderer("COMBOBOX", 5, 0); } /// /// Gets or sets a value indicating whether your code or the operating system will handle drawing of elements in the list. /// - /// One of the enumeration values. The default is . - /// - /// - /// - /// - /// - /// + /// One of the enumeration values. The default is . + /// [DefaultValue(DrawMode.OwnerDrawFixed), Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new DrawMode DrawMode { - get => base.DrawMode; set => base.DrawMode = value; + get => base.DrawMode; + set => base.DrawMode = value; } - /// - /// Gets or sets a value specifying the style of the combo box. - /// - /// One of the values. The default is DropDown. - /// - /// - /// - /// - /// - /// + /// Gets or sets a value specifying the style of the combo box. + /// One of the values. The default is DropDown. + /// [DefaultValue(ComboBoxStyle.DropDownList), Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new ComboBoxStyle DropDownStyle { - get => base.DropDownStyle; set => base.DropDownStyle = value; + get => base.DropDownStyle; + set => base.DropDownStyle = value; } - /// - /// Gets or sets the state of the combobox. - /// - /// - /// The state. - /// + /// Gets or sets the state of the combobox. + /// The state. private ComboBoxState State { get => currentState; @@ -95,28 +75,25 @@ namespace Vanara.Windows.Forms newState = value; if (diff) { - if (animationsNeedCleanup && IsHandleCreated) BufferedPaintStopAllAnimations(Handle); + if (animationsNeedCleanup && IsHandleCreated && !IsDisposed) + BufferedPaintStopAllAnimations(Handle); Invalidate(); } } } - /// - /// Determines whether an item is enabled. - /// + /// Determines whether an item is enabled. /// The index of the item. - /// - /// true if enabled; otherwise, false. - /// + /// true if enabled; otherwise, false. public bool IsItemEnabled(int idx) => !(idx > -1 && idx < Items.Count && Items[idx] is IEnableable && !((IEnableable)Items[idx]).Enabled); /// - /// Releases the unmanaged resources used by the and optionally releases the managed resources. + /// Releases the unmanaged resources used by the and optionally releases the managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected override void Dispose(bool disposing) { - if (animationsNeedCleanup) + if (animationsNeedCleanup && !IsDisposed) { BufferedPaintUnInit(); animationsNeedCleanup = false; @@ -124,10 +101,8 @@ namespace Vanara.Windows.Forms base.Dispose(disposing); } - /// - /// Raises the event. - /// - /// A that contains the event data. + /// Raises the event. + /// A that contains the event data. protected override void OnDrawItem(DrawItemEventArgs e) { var itemString = e.Index >= 0 ? GetItemText(Items[e.Index]) : string.Empty; @@ -153,51 +128,45 @@ namespace Vanara.Windows.Forms base.OnDrawItem(e); } - /// - /// Raises the event. - /// - /// An that contains the event data. + /// Raises the event. + /// An that contains the event data. protected override void OnDropDown(EventArgs e) { base.OnDropDown(e); State = ComboBoxState.Pressed; } - /// - /// Raises the event. - /// - /// An that contains the event data. + /// Raises the event. + /// An that contains the event data. protected override void OnDropDownClosed(EventArgs e) { base.OnDropDownClosed(e); State = ComboBoxState.Normal; } - /// - /// Raises the event. - /// - /// An that contains the event data. + /// Raises the event. + /// An that contains the event data. protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); if (vsr != null) + { + BufferedPaintInit(); animationsNeedCleanup = true; + } } - /// - /// Raises the event. - /// - /// An that contains the event data. + /// Raises the event. + /// An that contains the event data. protected override void OnHandleDestroyed(EventArgs e) { - dropDownWindow?.DestroyHandle(); + dropDownWindow?.ReleaseHandle(); + dropDownWindow = null; base.OnHandleDestroyed(e); } - /// - /// Raises the event. - /// - /// A that contains the event data. + /// Raises the event. + /// A that contains the event data. protected override void OnKeyPress(KeyPressEventArgs e) { var idx = FindEnabledString(e.KeyChar.ToString(), SelectedIndex); @@ -206,40 +175,32 @@ namespace Vanara.Windows.Forms base.OnKeyPress(e); } - /// - /// Raises the event. - /// - /// An that contains the event data. + /// Raises the event. + /// An that contains the event data. protected override void OnLostFocus(EventArgs e) { base.OnLostFocus(e); Invalidate(); } - /// - /// Raises the event. - /// - /// A that contains the event data. + /// Raises the event. + /// A that contains the event data. protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); State = ComboBoxState.Pressed; } - /// - /// Raises the event. - /// - /// An that contains the event data. + /// Raises the event. + /// An that contains the event data. protected override void OnMouseEnter(EventArgs e) { base.OnMouseEnter(e); State = ComboBoxState.Hot; } - /// - /// Raises the event. - /// - /// An that contains the event data. + /// Raises the event. + /// An that contains the event data. protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); @@ -247,10 +208,8 @@ namespace Vanara.Windows.Forms State = ComboBoxState.Normal; } - /// - /// Raises the event. - /// - /// A that contains the event data. + /// Raises the event. + /// A that contains the event data. protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); @@ -258,28 +217,26 @@ namespace Vanara.Windows.Forms State = ComboBoxState.Hot; } - /// - /// Raises the event. - /// - /// A that contains the event data. + /// Raises the event. + /// A that contains the event data. protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - BufferedPaint.PaintAnimation(e.Graphics, this, ClientRectangle, PaintControl, currentState, Enabled ? newState : ComboBoxState.Disabled, (a,b) => (int)vsr.GetTransitionDuration((int)a, (int)b)); + + if (IsDisposed) + return; + + BufferedPaint.PaintAnimation(e.Graphics, this, ClientRectangle, PaintControl, currentState, Enabled ? newState : ComboBoxState.Disabled, (a, b) => (int)vsr.GetTransitionDuration((int)a, (int)b)); } - /// - /// Paints the background of the control. - /// - /// A that contains information about the control to paint. + /// Paints the background of the control. + /// A that contains information about the control to paint. protected override void OnPaintBackground(PaintEventArgs pevent) { // don't paint the control's background } - /// - /// Paints the control. - /// + /// Paints the control. /// The dc. /// The bounds. /// State of the current. @@ -348,14 +305,12 @@ namespace Vanara.Windows.Forms } } - /// - /// Processes a command key. - /// - /// A , passed by reference, that represents the window message to process. - /// One of the values that represents the key to process. - /// - /// true if the character was processed by the control; otherwise, false. - /// + /// Processes a command key. + /// + /// A , passed by reference, that represents the window message to process. + /// + /// One of the values that represents the key to process. + /// true if the character was processed by the control; otherwise, false. protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { var visItems = DropDownHeight / ItemHeight; @@ -372,11 +327,17 @@ namespace Vanara.Windows.Forms return true; case Keys.PageDown: - SelectedIndex = SelectedIndex + visItems > Items.Count ? GetNextEnabledItemIndex(Items.Count, false) : GetNextEnabledItemIndex(SelectedIndex + visItems, true); + if (SelectedIndex + visItems > Items.Count) + SelectedIndex = GetNextEnabledItemIndex(Items.Count, false); + else + SelectedIndex = GetNextEnabledItemIndex(SelectedIndex + visItems, true); return true; case Keys.PageUp: - SelectedIndex = SelectedIndex - visItems < 0 ? GetNextEnabledItemIndex(-1, true) : GetNextEnabledItemIndex(SelectedIndex - visItems, false); + if (SelectedIndex - visItems < 0) + SelectedIndex = GetNextEnabledItemIndex(-1, true); + else + SelectedIndex = GetNextEnabledItemIndex(SelectedIndex - visItems, false); return true; case Keys.Home: @@ -388,8 +349,8 @@ namespace Vanara.Windows.Forms return true; case Keys.Enter: - var pt = dropDownWindow.MapPointToClient(Cursor.Position); - var idx = dropDownWindow.IndexFromPoint(pt.X, pt.Y); + var pt = dropDownWindow?.MapPointToClient(Cursor.Position) ?? default; + var idx = dropDownWindow?.IndexFromPoint(pt.X, pt.Y) ?? default; if (idx >= 0 && IsItemEnabled(idx)) return false; DroppedDown = false; @@ -402,14 +363,12 @@ namespace Vanara.Windows.Forms return base.ProcessCmdKey(ref msg, keyData); } - /// - /// Processes Windows messages. - /// - /// The Windows to process. + /// Processes Windows messages. + /// The Windows to process. protected override void WndProc(ref Message m) { base.WndProc(ref m); - if ((int)(long)m.WParam == 0x3e80001) + if ((int)(long)m.WParam == 0x3e80001 && !IsDisposed) { dropDownWindow = new ListBoxNativeWindow(m.LParam, this); } @@ -419,7 +378,7 @@ namespace Vanara.Windows.Forms { if (str != null) { - if ((startIndex < -1) || (startIndex >= Items.Count)) + if (startIndex < -1 || startIndex >= Items.Count) return -1; var length = str.Length; var num2 = 0; @@ -475,7 +434,7 @@ namespace Vanara.Windows.Forms protected override void WndProc(ref Message m) { - if (m.Msg == 0x0202 || m.Msg == 0x0201 || m.Msg == 0x0203) /* WM_LBUTTONUP or WM_LBUTTONDOWN or WM_LBUTTONDBLCLK */ + if (!Parent.IsDisposed && m.Msg == 0x0202 || m.Msg == 0x0201 || m.Msg == 0x0203) /* WM_LBUTTONUP or WM_LBUTTONDOWN or WM_LBUTTONDBLCLK */ { var idx = IndexFromPoint(SignedLOWORD(m.LParam), SignedHIWORD(m.LParam)); if (idx >= 0 && !Parent.IsItemEnabled(idx))