ListBox.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / ListBox.cs / 1305376 / ListBox.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 */ 
namespace System.Windows.Forms {
    using System.Runtime.Serialization.Formatters; 
    using System.Runtime.Remoting;
    using System.Runtime.InteropServices;

    using System.Diagnostics; 
    using System.Diagnostics.CodeAnalysis;
 
    using System; 
    using System.Security;
    using System.Security.Permissions; 
    using System.Globalization;
    using System.Windows.Forms.Layout;

    using System.Drawing.Design; 
    using System.ComponentModel;
    using System.Windows.Forms.ComponentModel; 
    using System.Windows.Forms.VisualStyles; 

    using System.Collections; 
    using System.Drawing;
    using Microsoft.Win32;
    using System.Text;
 
    /// 
    ///  
    /// 
    ///     This is a control that presents a list of items to the user.  They may be
    ///     navigated using the keyboard, or the scrollbar on the right side of the 
    ///     control.  One or more items may be selected as well.
    /// 
    ///
    ///     The preferred way to add items is to set them all via an array at once, 
    ///     which is definitely the most efficient way.  The following is an example
    ///     of this: 
    ///  
    /// 
    ///     ListBox lb = new ListBox(); 
    ///     //     set up properties on the listbox here.
    ///     lb.Items.All = new String [] {
    ///     "A",
    ///     "B", 
    ///     "C",
    ///     "D"}; 
    ///  
    /// 
    [ 
    ComVisible(true),
    ClassInterface(ClassInterfaceType.AutoDispatch),
    Designer("System.Windows.Forms.Design.ListBoxDesigner, " + AssemblyRef.SystemDesign),
    DefaultEvent("SelectedIndexChanged"), 
    DefaultProperty("Items"),
    DefaultBindingProperty("SelectedValue"), 
    SRDescription(SR.DescriptionListBox) 
    ]
    public class ListBox : ListControl { 
        /// 
        /// 
        ///     while doing a search, if no matches are found, this is returned
        ///  
        public const int NoMatches = NativeMethods.LB_ERR;
        ///  
        ///  
        ///     The default item height for an owner-draw ListBox.
        ///  
        public const int DefaultItemHeight = 13; // 13 == listbox's non-ownerdraw item height.  That's with Win2k and
        // the default font; on other platforms and with other fonts, it may be different.

        private const int maxWin9xHeight = 32767; //Win9x doesn't deal with height > 32K 

        private static readonly object EVENT_SELECTEDINDEXCHANGED = new object(); 
        private static readonly object EVENT_DRAWITEM             = new object(); 
        private static readonly object EVENT_MEASUREITEM          = new object();
 
        static bool checkedOS = false;
        static bool runningOnWin2K = true;

        SelectedObjectCollection selectedItems; 
        SelectedIndexCollection selectedIndices;
        ObjectCollection itemsCollection; 
 
        //
 
        int itemHeight = DefaultItemHeight;
        int columnWidth;
        int requestedHeight;
        int topIndex; 
        int horizontalExtent = 0;
        int maxWidth = -1; 
        int updateCount = 0; 

        bool sorted = false; 
        bool scrollAlwaysVisible = false;
        bool integralHeight = true;
        bool integralHeightAdjust = false;
        bool multiColumn = false; 
        bool horizontalScrollbar = false;
        bool useTabStops = true; 
        bool useCustomTabOffsets = false; 
        bool fontIsChanged = false;
        bool doubleClickFired = false; 
        bool selectedValueChangedFired = false;

        DrawMode drawMode = System.Windows.Forms.DrawMode.Normal;
        BorderStyle borderStyle = System.Windows.Forms.BorderStyle.Fixed3D; 
        SelectionMode selectionMode = System.Windows.Forms.SelectionMode.One;
 
        // VsWhidbey : 447524 
        SelectionMode cachedSelectionMode = System.Windows.Forms.SelectionMode.One;
        //We need to know that we are in middle of handleRecreate through Setter of SelectionMode. 
        //In this case we set a bool denoting that we are changing SelectionMode and
        //in this case we should always use the cachedValue instead of the currently set value.
        //We need to change this in the count as well as SelectedIndex code where we access the SelectionMode.
        private bool selectionModeChanging = false; 

        ///  
        ///     This value stores the array of custom tabstops in the listbox. the array should be populated by 
        ///     integers in a ascending order.
        ///  
        private IntegerCollection customTabOffsets;

        /// 
        ///  
        ///     Creates a basic win32 list box with default values for everything.
        ///  
        public ListBox() : base() { 
            SetStyle(ControlStyles.UserPaint |
                     ControlStyles.StandardClick | 
                     ControlStyles.UseTextForAccessibility, false);

            // this class overrides GetPreferredSizeCore, let Control automatically cache the result
            SetState2(STATE2_USEPREFERREDSIZECACHE, true); 

            SetBounds(0, 0, 120, 96); 
 
            requestedHeight = Height;
        } 

        /// 
        public override Color BackColor {
            get { 
                if (ShouldSerializeBackColor()) {
                    return base.BackColor; 
                } 
                else {
                    return SystemColors.Window; 
                }
            }
            set {
                base.BackColor = value; 
            }
        } 
 
        /// 
        ///  
        ///    [To be supplied.]
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public override Image BackgroundImage { 
            get {
                return base.BackgroundImage; 
            } 
            set {
                base.BackgroundImage = value; 
            }
        }

        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        new public event EventHandler BackgroundImageChanged { 
            add {
                base.BackgroundImageChanged += value; 
            }
            remove {
                base.BackgroundImageChanged -= value;
            } 
        }
 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public override ImageLayout BackgroundImageLayout {
            get { 
                return base.BackgroundImageLayout;
            } 
            set { 
                base.BackgroundImageLayout = value;
            } 
        }

        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public event EventHandler BackgroundImageLayoutChanged { 
            add { 
                base.BackgroundImageLayoutChanged += value;
            } 
            remove {
                base.BackgroundImageLayoutChanged -= value;
            }
        } 

        ///  
        ///  
        ///     Retrieves the current border style.  Values for this are taken from
        ///     The System.Windows.Forms.BorderStyle enumeration. 
        /// 
        [
        SRCategory(SR.CatAppearance),
        DefaultValue(BorderStyle.Fixed3D), 
        DispId(NativeMethods.ActiveX.DISPID_BORDERSTYLE),
        SRDescription(SR.ListBoxBorderDescr) 
        ] 
        public BorderStyle BorderStyle {
            get { 
                return borderStyle;
            }

            set { 
                //valid values are 0x0 to 0x2
                if (!ClientUtils.IsEnumValid(value, (int)value, (int)BorderStyle.None, (int)BorderStyle.Fixed3D)){ 
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(BorderStyle)); 
                }
 
                if (value != borderStyle) {
                    borderStyle = value;
                    RecreateHandle();
                    // Avoid the listbox and textbox behavior in Collection editors 
                    //
                    integralHeightAdjust = true; 
                    try { 
                        Height = requestedHeight;
                    } 
                    finally {
                        integralHeightAdjust = false;
                    }
                } 
            }
        } 
 
        /// 
        ///  
        /// 
        [
        SRCategory(SR.CatBehavior),
        Localizable(true), 
        DefaultValue(0),
        SRDescription(SR.ListBoxColumnWidthDescr) 
        ] 
        public int ColumnWidth {
            get { 
                return columnWidth;
            }

            set { 
                if (value < 0) {
                    throw new ArgumentException(SR.GetString(SR.InvalidLowBoundArgumentEx, "value", 
                                                             (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); 
                }
                if (columnWidth != value) { 
                    columnWidth = value;
                    // if it's zero, we need to reset, and only way to do
                    // that is to recreate the handle.
                    if (columnWidth == 0) { 
                        RecreateHandle();
                    } 
                    else if (IsHandleCreated) { 
                        SendMessage(NativeMethods.LB_SETCOLUMNWIDTH, columnWidth, 0);
                    } 
                }
            }
        }
 
        /// 
        ///  
        ///     Retrieves the parameters needed to create the handle.  Inheriting classes 
        ///     can override this to provide extra functionality.  They should not,
        ///     however, forget to call base.getCreateParams() first to get the struct 
        ///     filled up with the basic info.
        /// 
        /// 
        protected override CreateParams CreateParams { 
            [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
            get { 
                CreateParams cp = base.CreateParams; 
                cp.ClassName = "LISTBOX";
 
                cp.Style |= NativeMethods.WS_VSCROLL | NativeMethods.LBS_NOTIFY | NativeMethods.LBS_HASSTRINGS;
                if (scrollAlwaysVisible) cp.Style |= NativeMethods.LBS_DISABLENOSCROLL;
                if (!integralHeight) cp.Style |= NativeMethods.LBS_NOINTEGRALHEIGHT;
                if (useTabStops) cp.Style |= NativeMethods.LBS_USETABSTOPS; 

                switch (borderStyle) { 
                    case BorderStyle.Fixed3D: 
                        cp.ExStyle |= NativeMethods.WS_EX_CLIENTEDGE;
                        break; 
                    case BorderStyle.FixedSingle:
                        cp.Style |= NativeMethods.WS_BORDER;
                        break;
                } 

                if (multiColumn) { 
                    cp.Style |= NativeMethods.LBS_MULTICOLUMN | NativeMethods.WS_HSCROLL; 
                }
                else if (horizontalScrollbar) { 
                    cp.Style |= NativeMethods.WS_HSCROLL;
                }

                switch (selectionMode) { 
                    case SelectionMode.None:
                        cp.Style |= NativeMethods.LBS_NOSEL; 
                        break; 
                    case SelectionMode.MultiSimple:
                        cp.Style |= NativeMethods.LBS_MULTIPLESEL; 
                        break;
                    case SelectionMode.MultiExtended:
                        cp.Style |= NativeMethods.LBS_EXTENDEDSEL;
                        break; 
                    case SelectionMode.One:
                        break; 
                } 

                switch (drawMode) { 
                    case DrawMode.Normal:
                        break;
                    case DrawMode.OwnerDrawFixed:
                        cp.Style |= NativeMethods.LBS_OWNERDRAWFIXED; 
                        break;
                    case DrawMode.OwnerDrawVariable: 
                        cp.Style |= NativeMethods.LBS_OWNERDRAWVARIABLE; 
                        break;
                } 

                return cp;
            }
        } 

 
        ///  
        /// 
        ///     Enables a list box to recognize and expand tab characters when drawing 
        ///     its strings using the CustomTabOffsets integer array.
        /// 
        [
        SRCategory(SR.CatBehavior), 
        DefaultValue(false),
        Browsable(false) 
        ] 
        public bool UseCustomTabOffsets {
            get { 
                return useCustomTabOffsets;
            }
            set {
                if (useCustomTabOffsets != value) { 
                    useCustomTabOffsets = value;
                    RecreateHandle(); 
                } 
            }
        } 

        /// 
        protected override Size DefaultSize {
            get { 
                return new Size(120, 96);
            } 
        } 

        ///  
        /// 
        ///     Retrieves the style of the listbox.  This will indicate if the system
        ///     draws it, or if the user paints each item manually.  It also indicates
        ///     whether or not items have to be of the same height. 
        /// 
        [ 
        SRCategory(SR.CatBehavior), 
        DefaultValue(DrawMode.Normal),
        SRDescription(SR.ListBoxDrawModeDescr), 
        RefreshProperties(RefreshProperties.Repaint)
        ]
        public virtual DrawMode DrawMode {
            get { 
                return drawMode;
            } 
 
            set {
                //valid values are 0x0 to 0x2 
                if (!ClientUtils.IsEnumValid(value, (int)value, (int)DrawMode.Normal, (int)DrawMode.OwnerDrawVariable))
                {
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(DrawMode));
                } 
                if (drawMode != value) {
                    if (MultiColumn && value == DrawMode.OwnerDrawVariable) { 
                        throw new ArgumentException(SR.GetString(SR.ListBoxVarHeightMultiCol), "value"); 
                    }
                    drawMode = value; 
                    RecreateHandle();
                    if (drawMode == DrawMode.OwnerDrawVariable) {
                        // VSWhidbey 139179 - force a layout after RecreateHandle() completes because now
                        // the LB is definitely fully populated and can report a preferred size accurately. 
                        LayoutTransaction.DoLayoutIf(AutoSize, this.ParentInternal, this, PropertyNames.DrawMode);
                    } 
                } 
            }
        } 

        // Used internally to find the currently focused item
        //
        internal int FocusedIndex { 
            get {
                if (IsHandleCreated) { 
                    return unchecked( (int) (long)SendMessage(NativeMethods.LB_GETCARETINDEX, 0, 0)); 
                }
 
                return -1;
            }
        }
 
        /// 
        // VSWhidbey 95179: The scroll bars don't display properly when the IntegralHeight == false 
        // and the control is resized before the font size is change and the new font size causes 
        // the height of all the items to exceed the new height of the control. This is a bug in
        // the control, but can be easily worked around by removing and re-adding all the items. 
        public override Font Font {
            get {
                return base.Font;
            } 
            set {
                base.Font = value; 
 
                if (false == integralHeight) {
                    // VSWhidbey 95179: Refresh the list to force the scroll bars to display 
                    // when the integral height is false.
                    RefreshItems();
                }
            } 
        }
 
        ///  
        public override Color ForeColor {
            get { 
                if (ShouldSerializeForeColor()) {
                    return base.ForeColor;
                }
                else { 
                    return SystemColors.WindowText;
                } 
            } 
            set {
                base.ForeColor = value; 
            }
        }

        ///  
        /// 
        ///     Indicates the width, in pixels, by which a list box can be scrolled horizontally (the scrollable width). 
        ///     This property will only have an effect if HorizontalScrollbars is true. 
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(0),
        Localizable(true),
        SRDescription(SR.ListBoxHorizontalExtentDescr) 
        ]
        public int HorizontalExtent { 
            get { 
                return horizontalExtent;
            } 

            set {
                if (value != horizontalExtent) {
                    horizontalExtent = value; 
                    UpdateHorizontalExtent();
                } 
            } 
        }
 
        /// 
        /// 
        ///     Indicates whether or not the ListBox should display a horizontal scrollbar
        ///     when the items extend beyond the right edge of the ListBox. 
        ///     If true, the scrollbar will automatically set its extent depending on the length
        ///     of items in the ListBox. The exception is if the ListBox is owner-draw, in 
        ///     which case HorizontalExtent will need to be explicitly set. 
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(false),
        Localizable(true),
        SRDescription(SR.ListBoxHorizontalScrollbarDescr) 
        ]
        public bool HorizontalScrollbar { 
            get { 
                return horizontalScrollbar;
            } 

            set {
                if (value != horizontalScrollbar) {
                    horizontalScrollbar = value; 

                    // There seems to be a bug in the native ListBox in that the addition 
                    // of the horizontal scroll bar does not get reflected in the control 
                    // rightaway. So, we refresh the items here.
                    RefreshItems(); 

                    // Only need to recreate the handle if not MultiColumn
                    // (HorizontalScrollbar has no effect on a MultiColumn listbox)
                    // 
                    if (!MultiColumn) {
                        RecreateHandle(); 
                    } 
                }
            } 
        }

        /// 
        ///  
        ///     Indicates if the listbox should avoid showing partial Items.  If so,
        ///     then only full items will be displayed, and the listbox will be resized 
        ///     to prevent partial items from being shown.  Otherwise, they will be 
        ///     shown
        ///  
        [
        SRCategory(SR.CatBehavior),
        DefaultValue(true),
        Localizable(true), 
        SRDescription(SR.ListBoxIntegralHeightDescr),
        RefreshProperties(RefreshProperties.Repaint) 
        ] 
        public bool IntegralHeight {
            get { 
                return integralHeight;
            }

            set { 
                if (integralHeight != value) {
                    integralHeight = value; 
                    RecreateHandle(); 
                    // Avoid the listbox and textbox behaviour in Collection editors
                    // 

                    integralHeightAdjust = true;
                    try {
                        Height = requestedHeight; 
                    }
                    finally { 
                        integralHeightAdjust = false; 
                    }
                } 
            }
        }

        ///  
        /// 
        ///     
        ///       Returns 
        ///       the height of an item in an owner-draw list box.
        ///  
        [
        SRCategory(SR.CatBehavior),
        DefaultValue(DefaultItemHeight),
        Localizable(true), 
        SRDescription(SR.ListBoxItemHeightDescr),
        RefreshProperties(RefreshProperties.Repaint) 
        ] 
        public virtual int ItemHeight {
            get { 
                if (drawMode == DrawMode.OwnerDrawFixed ||
                    drawMode == DrawMode.OwnerDrawVariable) {
                    return itemHeight;
                } 

                return GetItemHeight(0); 
            } 

            set { 
                if (value < 1 || value > 255) {
                    throw new ArgumentOutOfRangeException("ItemHeight", SR.GetString(SR.InvalidExBoundArgument, "ItemHeight", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture), "256"));
                }
                if (itemHeight != value) { 
                    itemHeight = value;
                    if (drawMode == DrawMode.OwnerDrawFixed && IsHandleCreated) { 
                        BeginUpdate(); 
                        SendMessage(NativeMethods.LB_SETITEMHEIGHT, 0, value);
 
                        // Changing the item height might require a resize for IntegralHeight list boxes
                        //
                        if (IntegralHeight) {
                            Size oldSize = Size; 
                            Size = new Size(oldSize.Width + 1, oldSize.Height);
                            Size = oldSize; 
                        } 

                        EndUpdate(); 
                    }
                }
            }
        } 

        ///  
        ///  
        ///     Collection of items in this listbox.
        ///  
        [
        SRCategory(SR.CatData),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        Localizable(true), 
        SRDescription(SR.ListBoxItemsDescr),
        Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)), 
        MergableProperty(false) 
        ]
        public ObjectCollection Items { 
            get {
                if (itemsCollection == null) {
                    itemsCollection = CreateItemCollection();
                } 
                return itemsCollection;
            } 
        } 

        // Computes the maximum width of all items in the ListBox 
        //
        internal virtual int MaxItemWidth {
            get {
 
                if (horizontalExtent > 0) {
                    return horizontalExtent; 
                } 

                if (DrawMode != DrawMode.Normal) { 
                    return -1;
                }

                // Return cached maxWidth if available 
                //
                if (maxWidth > -1) { 
                    return maxWidth; 
                }
 
                // Compute maximum width
                //
                maxWidth = ComputeMaxItemWidth(maxWidth);
 
                return maxWidth;
            } 
        } 

        ///  
        /// 
        ///    
        ///       Indicates if the listbox is multi-column
        ///       or not. 
        /// 
        [ 
        SRCategory(SR.CatBehavior), 
        DefaultValue(false),
        SRDescription(SR.ListBoxMultiColumnDescr) 
        ]
        public bool MultiColumn {
            get {
                return multiColumn; 
            }
            set { 
                if (multiColumn != value) { 
                    if (value && drawMode == DrawMode.OwnerDrawVariable) {
                        throw new ArgumentException(SR.GetString(SR.ListBoxVarHeightMultiCol), "value"); 
                    }
                    multiColumn = value;
                    RecreateHandle();
                } 
            }
        } 
 
        /// 
        ///  
        ///     The total height of the items in the list box.
        /// 
        [
        Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        SRDescription(SR.ListBoxPreferredHeightDescr) 
        ] 
        public int PreferredHeight {
            get { 
                int height = 0;

                if (drawMode == DrawMode.OwnerDrawVariable) {
                    // VSWhidbey 139179 - don't try to get item heights from the LB when items haven't been 
                    // added to the LB yet. Just return current height.
                    if (RecreatingHandle || GetState(STATE_CREATINGHANDLE)) { 
                        height = this.Height; 
                    }
                    else { 
                        if (itemsCollection != null) {
                            int cnt = itemsCollection.Count;
                            for (int i = 0; i < cnt; i++) {
                                height += GetItemHeight(i); 
                            }
                        } 
                    } 
                }
                else { 
                    //VSWhidbey #148270
                    //When the list is empty, we don't want to multiply by 0 here.
                    int cnt = (itemsCollection == null || itemsCollection.Count == 0) ? 1 : itemsCollection.Count;
                    height = GetItemHeight(0) * cnt; 
                }
 
                if (borderStyle != BorderStyle.None) { 
                    height += SystemInformation.BorderSize.Height * 4 + 3;
                } 

                return height;
            }
        } 

        internal override Size GetPreferredSizeCore(Size proposedConstraints) 
        { 
            int height = PreferredHeight;
            int width; 

            // Convert with a dummy height to add space required for borders
            // VSWhidbey #151141 -PreferredSize should return either the new
            // size of the control, or the default size if the handle has not been 
            // created
            if (IsHandleCreated) 
            { 
                width = SizeFromClientSize(new Size(MaxItemWidth, height)).Width;
                width += SystemInformation.VerticalScrollBarWidth + 4; 
            }
            else
            {
                return DefaultSize; 
            }
            return new Size(width, height) + Padding.Size; 
        } 

        ///  
        public override RightToLeft RightToLeft {
            get {
                if (!RunningOnWin2K) {
                    return RightToLeft.No; 
                }
                return base.RightToLeft; 
            } 
            set {
                base.RightToLeft = value; 
            }
        }

        static bool RunningOnWin2K { 
            get {
                if (!checkedOS) { 
                    if (Environment.OSVersion.Platform != System.PlatformID.Win32NT || 
                        Environment.OSVersion.Version.Major < 5) {
                        runningOnWin2K = false; 
                        checkedOS = true;
                    }
                }
                return runningOnWin2K; 
            }
        } 
 
        /// 
        ///  
        ///    
        ///       Gets or sets whether the scrollbar is shown at all times.
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(false), 
        Localizable(true), 
        SRDescription(SR.ListBoxScrollIsVisibleDescr)
        ] 
        public bool ScrollAlwaysVisible {
            get {
                return scrollAlwaysVisible;
            } 
            set {
                if (scrollAlwaysVisible != value) { 
                    scrollAlwaysVisible = value; 
                    RecreateHandle();
                } 
            }
        }

        ///  
        /// 
        ///    Indicates whether list currently allows selection of list items. 
        ///    For ListBox, this returns true unless SelectionMode is SelectionMode.None. 
        /// 
        protected override bool AllowSelection { 
            get {
                return selectionMode != SelectionMode.None;
            }
        } 

        ///  
        ///  
        ///     The index of the currently selected item in the list, if there
        ///     is one.  If the value is -1, there is currently no selection.  If the 
        ///     value is 0 or greater, than the value is the index of the currently
        ///     selected item.  If the MultiSelect property on the ListBox is true,
        ///     then a non-zero value for this property is the index of the first
        ///     selection 
        /// 
        [ 
        Browsable(false), 
        Bindable(true),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        SRDescription(SR.ListBoxSelectedIndexDescr)
        ]
        public override int SelectedIndex {
            get { 

                SelectionMode current = (selectionModeChanging) ? cachedSelectionMode : selectionMode; 
 
                if (current == SelectionMode.None) {
                    return -1; 
                }

                if (current == SelectionMode.One && IsHandleCreated) {
                    return unchecked( (int) (long)SendMessage(NativeMethods.LB_GETCURSEL, 0, 0)); 
                }
 
                if (itemsCollection != null && SelectedItems.Count > 0) { 
                    return Items.IndexOfIdentifier(SelectedItems.GetObjectAt(0));
                } 

                return -1;
            }
            set { 

                int itemCount = (itemsCollection == null) ? 0 : itemsCollection.Count; 
 
                if (value < -1 || value >= itemCount) {
                    throw new ArgumentOutOfRangeException("SelectedIndex", SR.GetString(SR.InvalidArgument, "SelectedIndex", (value).ToString(CultureInfo.CurrentCulture))); 
                }

                if (selectionMode == SelectionMode.None) {
                    throw new ArgumentException(SR.GetString(SR.ListBoxInvalidSelectionMode), "SelectedIndex"); 
                }
 
                if (selectionMode == SelectionMode.One && value != -1) { 

                    // Single select an individual value. 
                    int currentIndex = SelectedIndex;

                    if (currentIndex != value) {
                        if (currentIndex != -1) { 
                            SelectedItems.SetSelected(currentIndex, false);
                        } 
                        SelectedItems.SetSelected(value, true); 

                        if (IsHandleCreated) { 
                            NativeSetSelected(value, true);
                        }

                        OnSelectedIndexChanged(EventArgs.Empty); 
                    }
                } 
                else if (value == -1) { 
                    if (SelectedIndex != -1) {
                        ClearSelected(); 
                        // ClearSelected raises OnSelectedIndexChanged for us
                    }
                }
                else { 
                    if (!SelectedItems.GetSelected(value)) {
 
                        // Select this item while keeping any previously selected items selected. 
                        //
                        SelectedItems.SetSelected(value, true); 
                        if (IsHandleCreated) {
                            NativeSetSelected(value, true);
                        }
                        OnSelectedIndexChanged(EventArgs.Empty); 
                    }
                } 
            } 
        }
 
        /// 
        /// 
        ///     A collection of the indices of the selected items in the
        ///     list box. If there are no selected items in the list box, the result is 
        ///     an empty collection.
        ///  
        [ 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        SRDescription(SR.ListBoxSelectedIndicesDescr)
        ]
        public SelectedIndexCollection SelectedIndices {
            get { 
                if (selectedIndices == null) {
                    selectedIndices = new SelectedIndexCollection(this); 
                } 
                return selectedIndices;
            } 
        }

        /// 
        ///  
        ///     The value of the currently selected item in the list, if there
        ///     is one.  If the value is null, there is currently no selection.  If the 
        ///     value is non-null, then the value is that of the currently selected 
        ///     item. If the MultiSelect property on the ListBox is true, then a
        ///     non-null return value for this method is the value of the first item 
        ///     selected
        /// 
        [
        Browsable(false), 
        Bindable(true),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        SRDescription(SR.ListBoxSelectedItemDescr) 
        ]
        public object SelectedItem { 
            get {
                if (SelectedItems.Count > 0) {
                    return SelectedItems[0];
                } 

                return null; 
            } 
            set {
                if (itemsCollection != null) { 
                    if (value != null) {
                        int index = itemsCollection.IndexOf(value);
                        if (index != -1) {
                            SelectedIndex = index; 
                        }
                    } 
                    else { 
                        SelectedIndex = -1;
                    } 
                }
            }
        }
 
        /// 
        ///  
        ///     The collection of selected items. 
        /// 
        [ 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        SRDescription(SR.ListBoxSelectedItemsDescr)
        ] 
        public SelectedObjectCollection SelectedItems {
            get { 
                if (selectedItems == null) { 
                    selectedItems = new SelectedObjectCollection(this);
                } 
                return selectedItems;
            }
        }
 
        /// 
        ///  
        ///     Controls how many items at a time can be selected in the listbox. Valid 
        ///     values are from the System.Windows.Forms.SelectionMode enumeration.
        ///  
        [
        SRCategory(SR.CatBehavior),
        DefaultValue(SelectionMode.One),
        SRDescription(SR.ListBoxSelectionModeDescr) 
        ]
        public virtual SelectionMode SelectionMode { 
            get { 
                return selectionMode;
            } 
            set {
                if (!ClientUtils.IsEnumValid(value, (int)value, (int)SelectionMode.None, (int)SelectionMode.MultiExtended))
                {
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(SelectionMode)); 
                }
 
                if (selectionMode != value) { 
                    SelectedItems.EnsureUpToDate();
                    selectionMode = value; 
                    try
                    {
                        selectionModeChanging = true;
                        RecreateHandle(); 
                    }
                    finally 
                    { 
                        selectionModeChanging = false;
                        cachedSelectionMode = selectionMode; 
                        // update the selectedItems list and SelectedItems index collection
                        if (IsHandleCreated)
                        {
                            NativeUpdateSelection(); 
                        }
                    } 
                } 
            }
        } 

        /// 
        /// 
        ///     Indicates if the ListBox is sorted or not.  'true' means that strings in 
        ///     the list will be sorted alphabetically
        ///  
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(false), 
        SRDescription(SR.ListBoxSortedDescr)
        ]
        public bool Sorted {
            get { 
                return sorted;
            } 
            set { 
                if (sorted != value) {
                    sorted = value; 

                    if (sorted && itemsCollection != null && itemsCollection.Count >= 1) {
                        Sort();
                    } 
                }
            } 
        } 

        ///  
        /// 
        ///    [To be supplied.]
        /// 
        [ 
        Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        Bindable(false) 
        ]
        public override string Text { 
            get {
                if (SelectionMode != SelectionMode.None && SelectedItem != null) {
                    if (FormattingEnabled) {
                        return GetItemText(SelectedItem); 
                    } else {
                        return FilterItemOnProperty(SelectedItem).ToString(); 
                    } 
                }
                else { 
                    return base.Text;
                }
            }
            set { 
                base.Text = value;
 
                // Scan through the list items looking for the supplied text string.  If we find it, 
                // select it.
                // 
                if (SelectionMode != SelectionMode.None && value != null && (SelectedItem == null || !value.Equals(GetItemText(SelectedItem)))) {

                    int cnt = Items.Count;
                    for (int index=0; index < cnt; ++index) { 
                        if (String.Compare(value, GetItemText(Items[index]), true, CultureInfo.CurrentCulture) == 0) {
                            SelectedIndex = index; 
                            return; 
                        }
                    } 
                }
            }
        }
 
        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced)] 
        new public event EventHandler TextChanged {
            add { 
                base.TextChanged += value;
            }
            remove {
                base.TextChanged -= value; 
            }
        } 
 
        /// 
        ///  
        ///     The index of the first visible item in a list box. Initially
        ///     the item with index 0 is at the top of the list box, but if the list
        ///     box contents have been scrolled another item may be at the top.
        ///  
        [
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        SRDescription(SR.ListBoxTopIndexDescr)
        ] 
        public int TopIndex {
            get {
                if (IsHandleCreated) {
                    return unchecked( (int) (long)SendMessage(NativeMethods.LB_GETTOPINDEX, 0, 0)); 
                }
                else { 
                    return topIndex; 
                }
            } 
            set {
                if (IsHandleCreated) {
                    SendMessage(NativeMethods.LB_SETTOPINDEX, value, 0);
                } 
                else {
                    topIndex = value; 
                } 
            }
        } 

        /// 
        /// 
        ///     Enables a list box to recognize and expand tab characters when drawing 
        ///     its strings.
        ///  
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(true), 
        SRDescription(SR.ListBoxUseTabStopsDescr)
        ]
        public bool UseTabStops {
            get { 
                return useTabStops;
            } 
            set { 
                if (useTabStops != value) {
                    useTabStops = value; 
                    RecreateHandle();
                }
            }
        } 
        /// 
        ///  
        ///     Allows to set the width of the tabs between the items in the list box. 
        ///     The integer array should have the tab spaces in the ascending order.
        ///  
        [
        SRCategory(SR.CatBehavior),
        SRDescription(SR.ListBoxCustomTabOffsetsDescr),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
        Browsable(false)
        ] 
        public IntegerCollection CustomTabOffsets { 
            get {
                if (customTabOffsets == null) { 
                    customTabOffsets = new IntegerCollection(this);
                }
                return customTabOffsets;
            } 
        }
 
        ///  
        /// 
        ///     Performs the work of adding the specified items to the Listbox 
        /// 
        [Obsolete("This method has been deprecated.  There is no replacement.  http://go.microsoft.com/fwlink/?linkid=14202")]
        protected virtual void AddItemsCore(object[] value) {
            int count = value == null? 0: value.Length; 
            if (count == 0) {
                return; 
            } 

            Items.AddRangeInternal(value); 
        }

        /// 
        [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)] 
        public new event EventHandler Click {
            add { 
                base.Click += value; 
            }
            remove { 
                base.Click -= value;
            }
        }
 
        /// 
        [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)] 
        public new event MouseEventHandler MouseClick { 
            add {
                base.MouseClick += value; 
            }
            remove {
                base.MouseClick -= value;
            } 
        }
 
        ///  
        /// 
        ///     
        ///    [To be supplied.]
        ///    
        /// 
        [ 
        Browsable(false),
        EditorBrowsable(EditorBrowsableState.Never), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) 
        ]
        public new Padding Padding { 
            get { return base.Padding; }
            set { base.Padding = value;}
        }
 
        [
        Browsable(false), 
        EditorBrowsable(EditorBrowsableState.Never) 
        ]
        public new event EventHandler PaddingChanged { 
            add { base.PaddingChanged += value; }
            remove { base.PaddingChanged -= value; }
        }
 
        /// 
        ///  
        ///     ListBox / CheckedListBox Onpaint. 
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        public new event PaintEventHandler Paint {
            add {
                base.Paint += value;
            } 
            remove {
                base.Paint -= value; 
            } 
        }
 
        /// 
        /// 
        ///    [To be supplied.]
        ///  
        [SRCategory(SR.CatBehavior), SRDescription(SR.drawItemEventDescr)]
        public event DrawItemEventHandler DrawItem { 
            add { 
                Events.AddHandler(EVENT_DRAWITEM, value);
            } 
            remove {
                Events.RemoveHandler(EVENT_DRAWITEM, value);
            }
        } 

 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        [SRCategory(SR.CatBehavior), SRDescription(SR.measureItemEventDescr)]
        public event MeasureItemEventHandler MeasureItem {
            add { 
                Events.AddHandler(EVENT_MEASUREITEM, value);
            } 
            remove { 
                Events.RemoveHandler(EVENT_MEASUREITEM, value);
            } 
        }


        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        [SRCategory(SR.CatBehavior), SRDescription(SR.selectedIndexChangedEventDescr)]
        public event EventHandler SelectedIndexChanged { 
            add {
                Events.AddHandler(EVENT_SELECTEDINDEXCHANGED, value);
            }
            remove { 
                Events.RemoveHandler(EVENT_SELECTEDINDEXCHANGED, value);
            } 
        } 

        ///  
        /// 
        ///     While the preferred way to insert items is to set Items.All,
        ///     and set all the items at once, there are times when you may wish to
        ///     insert each item one at a time.  To help with the performance of this, 
        ///     it is desirable to prevent the ListBox from painting during these
        ///     operations.  This method, along with EndUpdate, is the preferred 
        ///     way of doing this.  Don't forget to call EndUpdate when you're done, 
        ///     or else the ListBox won't paint properly afterwards.
        ///  
        public void BeginUpdate() {
            BeginUpdateInternal();
            updateCount++;
        } 

        private void CheckIndex(int index) { 
            if (index < 0 || index >= Items.Count) 
                throw new ArgumentOutOfRangeException("index", SR.GetString(SR.IndexOutOfRange, index.ToString(CultureInfo.CurrentCulture)));
        } 

        private void CheckNoDataSource() {
            if (DataSource != null)
                throw new ArgumentException(SR.GetString(SR.DataSourceLocksItems)); 
        }
 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        protected virtual ObjectCollection CreateItemCollection() {
            return new ObjectCollection(this);
        } 

        internal virtual int ComputeMaxItemWidth(int oldMax) { 
            // pass LayoutUtils the collection of strings 
            string[] strings = new string[this.Items.Count];
 
            for (int i = 0; i < Items.Count; i ++) {
                strings[i] = GetItemText(Items[i]);
            }
 
            Size textSize = LayoutUtils.OldGetLargestStringSizeInCollection(Font, strings);
            return Math.Max(oldMax, textSize.Width); 
        } 

        ///  
        /// 
        ///     Unselects all currently selected items.
        /// 
        public void ClearSelected() { 

            bool hadSelection = false; 
 
            int itemCount = (itemsCollection == null) ? 0 : itemsCollection.Count;
            for (int x = 0; x < itemCount;x++) { 
                if (SelectedItems.GetSelected(x)) {
                    hadSelection = true;
                    SelectedItems.SetSelected(x, false);
                    if (IsHandleCreated) { 
                        NativeSetSelected(x, false);
                    } 
                } 
            }
 
            if (hadSelection) {
                OnSelectedIndexChanged(EventArgs.Empty);
            }
        } 

        ///  
        ///  
        ///     While the preferred way to insert items is to set Items.All,
        ///     and set all the items at once, there are times when you may wish to 
        ///     insert each item one at a time.  To help with the performance of this,
        ///     it is desirable to prevent the ListBox from painting during these
        ///     operations.  This method, along with BeginUpdate, is the preferred
        ///     way of doing this.  BeginUpdate should be called first, and this method 
        ///     should be called when you want the control to start painting again.
        ///  
        public void EndUpdate() { 
            EndUpdateInternal();
            --updateCount; 
        }

        /// 
        ///  
        ///     Finds the first item in the list box that starts with the given string.
        ///     The search is not case sensitive. 
        ///  
        public int FindString(string s) {
            return FindString(s, -1); 
        }

        /// 
        ///  
        ///     Finds the first item after the given index which starts with the given
        ///     string. The search is not case sensitive. 
        ///  
        public int FindString(string s, int startIndex) {
            if (s == null) return -1; 

            int itemCount = (itemsCollection == null) ? 0 : itemsCollection.Count;

            if (itemCount == 0) { 
                return -1;
            } 
 
            // VSWhidbey 95158: The last item in the list is still a valid starting point for a search.
            if (startIndex < -1 || startIndex >= itemCount) { 
                throw new ArgumentOutOfRangeException("startIndex");
            }

            // Always use the managed FindStringInternal instead of LB_FINDSTRING. 
            // The managed version correctly handles Turkish I.
            return FindStringInternal(s, Items, startIndex, false); 
        } 

        ///  
        /// 
        ///     Finds the first item in the list box that matches the given string.
        ///     The strings must match exactly, except for differences in casing.
        ///  
        public int FindStringExact(string s) {
            return FindStringExact(s, -1); 
        } 

        ///  
        /// 
        ///     Finds the first item after the given index that matches the given
        ///     string. The strings must match excatly, except for differences in
        ///     casing. 
        /// 
        public int FindStringExact(string s, int startIndex) { 
            if (s == null) return -1; 

            int itemCount = (itemsCollection == null) ? 0 : itemsCollection.Count; 

            if (itemCount == 0) {
                return -1;
            } 

            // VSWhidbey 95158: The last item in the list is still a valid starting point for a search. 
            if (startIndex < -1 || startIndex >= itemCount) { 
                throw new ArgumentOutOfRangeException("startIndex");
            } 

            // Always use the managed FindStringInternal instead of LB_FINDSTRING.
            // The managed version correctly handles Turkish I.
            // 
            return FindStringInternal(s, Items, startIndex, true);
        } 
 
        /// 
        ///  
        ///     Returns the height of the given item in a list box. The index parameter
        ///     is ignored if drawMode is not OwnerDrawVariable.
        /// 
        public int GetItemHeight(int index) { 
            int itemCount = (itemsCollection == null) ? 0 : itemsCollection.Count;
 
            // Note: index == 0 is OK even if the ListBox currently has 
            // no items.
            // 
            if (index < 0 || (index > 0 && index >= itemCount))
                throw new ArgumentOutOfRangeException("index", SR.GetString(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture)));

            if (drawMode != DrawMode.OwnerDrawVariable) index = 0; 

            if (IsHandleCreated) { 
                int h = unchecked( (int) (long)SendMessage(NativeMethods.LB_GETITEMHEIGHT, index, 0)); 
                if (h == -1)
                    throw new Win32Exception(); 
                return h;
            }

            return itemHeight; 
        }
 
        ///  
        /// 
        ///     Retrieves a Rectangle object which describes the bounding rectangle 
        ///     around an item in the list.  If the item in question is not visible,
        ///     the rectangle will be outside the visible portion of the control.
        /// 
        public Rectangle GetItemRectangle(int index) { 
            CheckIndex(index);
            NativeMethods.RECT rect = new NativeMethods.RECT(); 
            SendMessage(NativeMethods.LB_GETITEMRECT, index, ref rect); 
            return Rectangle.FromLTRB(rect.left, rect.top, rect.right, rect.bottom);
        } 

        /// 
        ///     List box overrides GetScaledBounds to ensure we always scale the requested
        ///     height, not the current height. 
        /// 
        [EditorBrowsable(EditorBrowsableState.Advanced)] 
        protected override Rectangle GetScaledBounds(Rectangle bounds, SizeF factor, BoundsSpecified specified) { 
            // update bounds' height to use the requested height, not the current height.  These
            // can be different if integral height is turned on. 
            bounds.Height = requestedHeight;
            return base.GetScaledBounds(bounds, factor, specified);
        }
 
        /// 
        ///  
        ///     Tells you whether or not the item at the supplied index is selected 
        ///     or not.
        ///  
        public bool GetSelected(int index) {
            CheckIndex(index);
            return GetSelectedInternal(index);
        } 

        private bool GetSelectedInternal(int index) { 
            if (IsHandleCreated) { 
                int sel = unchecked( (int) (long)SendMessage(NativeMethods.LB_GETSEL, index, 0));
                if (sel == -1) { 
                    throw new Win32Exception();
                }
                return sel > 0;
            } 
            else {
                if (itemsCollection != null && SelectedItems.GetSelected(index)) { 
                    return true; 
                }
                return false; 
            }
        }

        ///  
        /// 
        ///     Retrieves the index of the item at the given coordinates. 
        ///  
        public int IndexFromPoint(Point p) {
            return IndexFromPoint(p.X, p.Y); 
        }

        /// 
        ///  
        ///     Retrieves the index of the item at the given coordinates.
        ///  
        public int IndexFromPoint(int x, int y) { 
            //NT4 SP6A : SendMessage Fails. So First check whether the point is in Client Co-ordinates and then
            //call Sendmessage. 
            //
            NativeMethods.RECT r = new NativeMethods.RECT();
            UnsafeNativeMethods.GetClientRect(new HandleRef(this, Handle), ref r);
            if (r.left <= x && x < r.right && r.top <= y && y < r.bottom) { 
                int index = unchecked( (int) (long)SendMessage(NativeMethods.LB_ITEMFROMPOINT, 0, unchecked( (int) (long)NativeMethods.Util.MAKELPARAM(x, y))));
                if (NativeMethods.Util.HIWORD(index) == 0) { 
                    // Inside ListBox client area 
                    return NativeMethods.Util.LOWORD(index);
                } 
            }

            return NoMatches;
        } 

        ///  
        ///     Adds the given item to the native combo box.  This asserts if the handle hasn't been 
        ///     created.
        ///  
        private int NativeAdd(object item) {
            Debug.Assert(IsHandleCreated, "Shouldn't be calling Native methods before the handle is created.");
            int insertIndex = unchecked( (int) (long)SendMessage(NativeMethods.LB_ADDSTRING, 0, GetItemText(item)));
 
            if (insertIndex == NativeMethods.LB_ERRSPACE) {
                throw new OutOfMemoryException(); 
            } 

            if (insertIndex == NativeMethods.LB_ERR) { 
                // On some platforms (e.g. Win98), the ListBox control
                // appears to return LB_ERR if there are a large number (>32000)
                // of items. It doesn't appear to set error codes appropriately,
                // so we'll have to assume that LB_ERR corresponds to item 
                // overflow.
                // 
                throw new OutOfMemoryException(SR.GetString(SR.ListBoxItemOverflow)); 
            }
 
            return insertIndex;
        }

        ///  
        ///     Clears the contents of the combo box.
        ///  
        private void NativeClear() { 
            Debug.Assert(IsHandleCreated, "Shouldn't be calling Native methods before the handle is created.");
            SendMessage(NativeMethods.LB_RESETCONTENT, 0, 0); 
        }

        /// 
        ///     Get the text stored by the native control for the specified list item. 
        /// 
        internal string NativeGetItemText(int index) { 
            int len = unchecked( (int) (long)SendMessage(NativeMethods.LB_GETTEXTLEN, index, 0)); 
            StringBuilder sb = new StringBuilder(len + 1);
            UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.LB_GETTEXT, index, sb); 
            return sb.ToString();
        }

        ///  
        ///     Inserts the given item to the native combo box at the index.  This asserts if the handle hasn't been
        ///     created or if the resulting insert index doesn't match the passed in index. 
        ///  
        private int NativeInsert(int index, object item) {
            Debug.Assert(IsHandleCreated, "Shouldn't be calling Native methods before the handle is created."); 
            int insertIndex = unchecked( (int) (long)SendMessage(NativeMethods.LB_INSERTSTRING, index, GetItemText(item)));

            if (insertIndex == NativeMethods.LB_ERRSPACE) {
                throw new OutOfMemoryException(); 
            }
 
            if (insertIndex == NativeMethods.LB_ERR) { 
                // On some platforms (e.g. Win98), the ListBox control
                // appears to return LB_ERR if there are a large number (>32000) 
                // of items. It doesn't appear to set error codes appropriately,
                // so we'll have to assume that LB_ERR corresponds to item
                // overflow.
                // 
                throw new OutOfMemoryException(SR.GetString(SR.ListBoxItemOverflow));
            } 
 
            Debug.Assert(insertIndex == index, "NativeListBox inserted at " + insertIndex + " not the requested index of " + index);
            return insertIndex; 
        }

        /// 
        ///     Removes the native item from the given index. 
        /// 
        private void NativeRemoveAt(int index) { 
            Debug.Assert(IsHandleCreated, "Shouldn't be calling Native methods before the handle is created."); 

            bool selected = (unchecked( (int) (long)SendMessage(NativeMethods.LB_GETSEL, (IntPtr)index, IntPtr.Zero)) > 0); 
            SendMessage(NativeMethods.LB_DELETESTRING, index, 0);

            //If the item currently selected is removed then we should fire a Selectionchanged event...
            //as the next time selected index returns -1... 

            if (selected) { 
                OnSelectedIndexChanged(EventArgs.Empty); 
            }
        } 

        /// 
        ///     Sets the selection of the given index to the native window.  This does not change
        ///     the collection; you must update the collection yourself. 
        /// 
        private void NativeSetSelected(int index, bool value) { 
            Debug.Assert(IsHandleCreated, "Should only call Native methods after the handle has been created"); 
            Debug.Assert(selectionMode != SelectionMode.None, "Guard against setting selection for None selection mode outside this code.");
 
            if (selectionMode == SelectionMode.One) {
                SendMessage(NativeMethods.LB_SETCURSEL, (value ? index : -1), 0);
            }
            else { 
                SendMessage(NativeMethods.LB_SETSEL, value? -1: 0, index);
            } 
        } 

        ///  
        ///     This is called by the SelectedObjectCollection in response to the first
        ///     query on that collection after we have called Dirty().  Dirty() is called
        ///     when we receive a LBN_SELCHANGE message.
        ///  
        private void NativeUpdateSelection() {
            Debug.Assert(IsHandleCreated, "Should only call native methods if handle is created"); 
 
            // Clear the selection state.
            // 
            int cnt = Items.Count;
            for (int i = 0; i < cnt; i++) {
                SelectedItems.SetSelected(i, false);
            } 

            int[] result = null; 
 
            switch (selectionMode) {
 
                case SelectionMode.One:
                    int index = unchecked( (int) (long)SendMessage(NativeMethods.LB_GETCURSEL, 0, 0));
                    if (index >= 0) result = new int[] {index};
                    break; 

                case SelectionMode.MultiSimple: 
                case SelectionMode.MultiExtended: 
                    int count = unchecked( (int) (long)SendMessage(NativeMethods.LB_GETSELCOUNT, 0, 0));
                    if (count > 0) { 
                        result = new int[count];
                        UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.LB_GETSELITEMS, count, result);
                    }
                    break; 
            }
 
            // Now set the selected state on the appropriate items. 
            //
            if (result != null) { 
                foreach(int i in result) {
                    SelectedItems.SetSelected(i, true);
                }
            } 
        }
 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        protected override void OnChangeUICues(UICuesEventArgs e) {

            // ListBox seems to get a bit confused when the UI cues change for the first 
            // time - it draws the focus rect when it shouldn't and vice-versa. So when
            // the UI cues change, we just do an extra invalidate to get it into the 
            // right state. 
            //
            Invalidate(); 

            base.OnChangeUICues(e);
        }
 
        /// 
        ///  
        ///     Actually goes and fires the drawItem event.  Inheriting controls 
        ///     should use this to know when the event is fired [this is preferable to
        ///     adding an event handler yourself for this event].  They should, 
        ///     however, remember to call base.onDrawItem(e); to ensure the event is
        ///     still fired to external listeners
        /// 
        protected virtual void OnDrawItem(DrawItemEventArgs e) { 
            DrawItemEventHandler handler = (DrawItemEventHandler)Events[EVENT_DRAWITEM];
            if (handler != null) { 
                handler(this, e); 
            }
        } 

        /// 
        /// 
        ///     We need to know when the window handle has been created so we can 
        ///     set up a few things, like column width, etc!  Inheriting classes should
        ///     not forget to call base.OnHandleCreated(). 
        ///  
        protected override void OnHandleCreated(EventArgs e) {
            base.OnHandleCreated(e); 


            //for getting the current Locale to set the Scrollbars...
            // 
            SendMessage(NativeMethods.LB_SETLOCALE, CultureInfo.CurrentCulture.LCID, 0);
 
            if (columnWidth != 0) { 
                SendMessage(NativeMethods.LB_SETCOLUMNWIDTH, columnWidth, 0);
            } 
            if (drawMode == DrawMode.OwnerDrawFixed) {
                SendMessage(NativeMethods.LB_SETITEMHEIGHT, 0, ItemHeight);
            }
 
            if (topIndex != 0) {
                SendMessage(NativeMethods.LB_SETTOPINDEX, topIndex, 0); 
            } 

            if (UseCustomTabOffsets && CustomTabOffsets != null) { 
                int wpar = CustomTabOffsets.Count;
                int[] offsets = new int[wpar];
                CustomTabOffsets.CopyTo(offsets, 0);
                UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.LB_SETTABSTOPS, wpar, offsets); 
            }
 
            if (itemsCollection != null) { 

                int count = itemsCollection.Count; 

                for(int i = 0; i < count; i++) {
                    NativeAdd(itemsCollection[i]);
 
                    if (selectionMode != SelectionMode.None) {
                        if (selectedItems != null) { 
                            selectedItems.PushSelectionIntoNativeListBox(i); 
                        }
                    } 
                }
            }
            if (selectedItems != null) {
                if (selectedItems.Count > 0 && selectionMode == SelectionMode.One) { 
                    SelectedItems.Dirty();
                    SelectedItems.EnsureUpToDate(); 
                } 
            }
            UpdateHorizontalExtent(); 
        }

        /// 
        ///  
        ///     Overridden to make sure that we set up and clear out items
        ///     correctly.  Inheriting controls should not forget to call 
        ///     base.OnHandleDestroyed() 
        /// 
        protected override void OnHandleDestroyed(EventArgs e) { 
            SelectedItems.EnsureUpToDate();
            if (Disposing) {
                itemsCollection = null;
            } 
            base.OnHandleDestroyed(e);
        } 
 
        /// 
        ///  
        ///    [To be supplied.]
        /// 
        protected virtual void OnMeasureItem(MeasureItemEventArgs e) {
            MeasureItemEventHandler handler = (MeasureItemEventHandler)Events[EVENT_MEASUREITEM]; 
            if (handler != null) {
                handler(this, e); 
            } 
        }
 
        /// 
        /// 
        ///    [To be supplied.]
        ///  
        protected override void OnFontChanged(EventArgs e) {
            base.OnFontChanged(e); 
 
            // Changing the font causes us to resize, always rounding down.
            // Make sure we do this after base.OnPropertyChanged, which sends the WM_SETFONT message 

            // Avoid the listbox and textbox behaviour in Collection editors
            //
            UpdateFontCache(); 
        }
 
 
        /// 
        ///  
        ///    We override this so we can re-create the handle if the parent has changed.
        /// 
        protected override void OnParentChanged(EventArgs e) {
            base.OnParentChanged(e); 
            //No need to RecreateHandle if we are removing the Listbox from controls collection...
            //so check the parent before recreating the handle... 
            if (this.ParentInternal != null) { 
                RecreateHandle();
            } 
        }

        /// 
        ///  
        ///    [To be supplied.]
        ///  
        protected override void OnResize(EventArgs e) { 

            base.OnResize(e); 

            // There are some repainting issues for RightToLeft - so invalidate when we resize.
            //
            if (RightToLeft == RightToLeft.Yes || this.HorizontalScrollbar) { 
                Invalidate();
            } 
 
        }
 
        /// 
        /// 
        ///     Actually goes and fires the selectedIndexChanged event.  Inheriting controls
        ///     should use this to know when the event is fired [this is preferable to 
        ///     adding an event handler on yourself for this event].  They should,
        ///     however, remember to call base.OnSelectedIndexChanged(e); to ensure the event is 
        ///     still fired to external listeners 
        /// 
        protected override void OnSelectedIndexChanged(EventArgs e) { 
            base.OnSelectedIndexChanged(e);

            // set the position in the dataSource, if there is any
            // we will only set the position in the currencyManager if it is different 
            // from the SelectedIndex. Setting CurrencyManager::Position (even w/o changing it)
            // calls CurrencyManager::EndCurrentEdit, and that will pull the dataFrom the controls 
            // into the backEnd. We do not need to do that. 
            //
            if (this.DataManager != null && DataManager.Position != SelectedIndex) { 
                //read this as "if everett or   (whidbey and selindex is valid)"
                if (!FormattingEnabled || this.SelectedIndex != -1)
                {
                    // VSWhidbey 95176: don't change dataManager position if we simply unselected everything. 
                    // (Doing so would cause the first LB item to be selected...)
                    this.DataManager.Position = this.SelectedIndex; 
                } 
            }
 
            // VSWhidbey 163411: Call the handler after updating the DataManager's position so that
            // the DataManager's selected index will be correct in an event handler.
            EventHandler handler = (EventHandler)Events[EVENT_SELECTEDINDEXCHANGED];
            if (handler != null) { 
                handler(this, e);
            } 
        } 

        ///  
        protected override void OnSelectedValueChanged(EventArgs e) {
            base.OnSelectedValueChanged(e);
            selectedValueChangedFired = true;
        } 

        ///  
        protected override void OnDataSourceChanged(EventArgs e) { 
            if (DataSource == null)
            { 
                BeginUpdate();
                SelectedIndex = -1;
                Items.ClearInternal();
                EndUpdate(); 
            }
            base.OnDataSourceChanged(e); 
            RefreshItems(); 
        }
 
        /// 
        protected override void OnDisplayMemberChanged(EventArgs e) {
            base.OnDisplayMemberChanged(e);
 
            // we want to use the new DisplayMember even if there is no data source
            RefreshItems(); 
 
            if (SelectionMode != SelectionMode.None && this.DataManager != null)
                this.SelectedIndex = this.DataManager.Position; 
        }

        /// 
        ///  
        ///     Forces the ListBox to invalidate and immediately
        ///     repaint itself and any children if OwnerDrawVariable. 
        ///  
        public override void Refresh() {
            if (drawMode == DrawMode.OwnerDrawVariable) { 
                //Fire MeasureItem for Each Item in the Listbox...
                int cnt = Items.Count;
                Graphics graphics = CreateGraphicsInternal();
 
                try
                { 
                    for (int i = 0; i < cnt; i++) { 
                        MeasureItemEventArgs mie = new MeasureItemEventArgs(graphics, i, ItemHeight);
                        OnMeasureItem(mie); 
                    }
                }
                finally {
                    graphics.Dispose(); 
                }
 
            } 
            base.Refresh();
        } 
        /// 
        /// 
        /// Reparses the objects, getting new text strings for them.
        ///  
        /// 
        protected override void RefreshItems() { 
 
            // Store the currently selected object collection.
            // 
            ObjectCollection savedItems = itemsCollection;

            // Clear the items.
            // 
            itemsCollection = null;
            selectedIndices = null; 
 
            if (IsHandleCreated) {
                NativeClear(); 
            }

            object[] newItems = null;
 
            // if we have a dataSource and a DisplayMember, then use it
            // to populate the Items collection 
            // 
            if (this.DataManager != null && this.DataManager.Count != -1) {
                newItems = new object[this.DataManager.Count]; 
                for(int i = 0; i < newItems.Length; i++) {
                    newItems[i] = this.DataManager[i];
                }
            } 
            else if (savedItems != null) {
                newItems = new object[savedItems.Count]; 
                savedItems.CopyTo(newItems, 0); 
            }
 
            // Store the current list of items
            //
            if (newItems != null) {
                Items.AddRangeInternal(newItems); 
            }
 
            // Restore the selected indices if SelectionMode allows it. 
            //
            if (SelectionMode != SelectionMode.None) { 
                if (this.DataManager != null) {
                    // put the selectedIndex in [....] w/ the position in the dataManager
                    this.SelectedIndex = this.DataManager.Position;
                } 
                else {
                    if (savedItems != null) { 
                        int cnt = savedItems.Count; 
                        for(int index = 0; index < cnt; index++) {
                            if (savedItems.InnerArray.GetState(index, SelectedObjectCollection.SelectedObjectMask)) { 
                                SelectedItem = savedItems[index];
                            }
                        }
                    } 
                }
            } 
 
        }
 
        /// 
        /// 
        /// Reparses the object at the given index, getting new text string for it.
        ///  
        /// 
        protected override void RefreshItem(int index) { 
            Items.SetItemInternal(index, Items[index]); 
        }
 
        public override void ResetBackColor() {
            base.ResetBackColor();
        }
 
        public override void ResetForeColor() {
            base.ResetForeColor(); 
        } 

 
        private void ResetItemHeight() {
            itemHeight = DefaultItemHeight;
        }
 
       [SuppressMessage("Microsoft.Portability", "CA1902:AvoidTestingForFloatingPointEquality")]
       protected override void ScaleControl(SizeF factor, BoundsSpecified specified) { 
 
           if (factor.Width != 1F && factor.Height != 1F) {
               UpdateFontCache(); 
           }
           base.ScaleControl(factor, specified);
       }
 

        ///  
        ///  
        ///     Overrides Control.SetBoundsCore to remember the requestedHeight.
        ///  
        /// 
        protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {

            // Avoid the listbox and textbox behaviour in Collection editors 
            //
 
 
            if (!integralHeightAdjust && height != Height)
                requestedHeight = height; 
            base.SetBoundsCore(x, y, width, height, specified);
        }

        ///  
        /// 
        ///     Performs the work of setting the specified items into the ListBox. 
        ///  
        protected override void SetItemsCore(IList value) {
                BeginUpdate(); 
                Items.ClearInternal();
                Items.AddRangeInternal(value);

                this.SelectedItems.Dirty(); 

                // if the list changed, we want to keep the same selected index 
                // CurrencyManager will provide the PositionChanged event 
                // it will be provided before changing the list though...
                if (this.DataManager != null) { 
                    if (this.DataSource is ICurrencyManagerProvider) {
                        // Everett ListControl's had a bug where they would not fire
                        // OnSelectedValueChanged if their list of items were refreshed.
                        // We fix this post-Everett. 
                        // However, for APPCOMPAT reasons, we only want to fix it when binding to
                        // Whidbey components. 
                        // vsw 547279. 
                        this.selectedValueChangedFired = false;
                    } 

                    if (IsHandleCreated) {
                        SendMessage(NativeMethods.LB_SETCURSEL, DataManager.Position, 0);
                    } 

                    // if the list changed and we still did not fire the 
                    // onselectedChanged event, then fire it now; 
                    if (!selectedValueChangedFired) {
                        OnSelectedValueChanged(EventArgs.Empty); 
                        selectedValueChangedFired = false;
                    }
                }
                EndUpdate(); 
        }
 
        ///  
        protected override void SetItemCore(int index, object value) {
            Items.SetItemInternal(index, value); 
        }

        /// 
        ///  
        ///     Allows the user to set an item as being selected or not.  This should
        ///     only be used with ListBoxes that allow some sort of multi-selection. 
        ///  
        public void SetSelected(int index, bool value) {
            int itemCount = (itemsCollection == null) ? 0: itemsCollection.Count; 
            if (index < 0 || index >= itemCount)
                throw new ArgumentOutOfRangeException("index", SR.GetString(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture)));

            if (selectionMode == SelectionMode.None) 
                throw new InvalidOperationException(SR.GetString(SR.ListBoxInvalidSelectionMode));
 
            SelectedItems.SetSelected(index, value); 
            if (IsHandleCreated) {
                NativeSetSelected(index, value); 
            }
            SelectedItems.Dirty();
            OnSelectedIndexChanged(EventArgs.Empty);
        } 

        ///  
        ///  
        ///     Sorts the items in the listbox.
        ///  
        protected virtual void Sort() {
            // This will force the collection to add each item back to itself
            // if sorted is now true, then the add method will insert the item
            // into the correct position 
            //
            CheckNoDataSource(); 
 
            SelectedObjectCollection currentSelections = SelectedItems;
            currentSelections.EnsureUpToDate(); 

            if (sorted && itemsCollection != null) {
                itemsCollection.InnerArray.Sort();
 
                // Now that we've sorted, update our handle
                // if it has been created. 
                if (IsHandleCreated) { 
                    NativeClear();
                    int count = itemsCollection.Count; 
                    for(int i = 0; i < count; i++) {
                        NativeAdd(itemsCollection[i]);
                        if (currentSelections.GetSelected(i)) {
                            NativeSetSelected(i, true); 
                        }
                    } 
                } 
            }
        } 

        /// 
        /// 
        ///     Returns a string representation for this control. 
        /// 
        ///  
        public override string ToString() { 

            string s = base.ToString(); 
            if (itemsCollection != null) {
                s += ", Items.Count: " + Items.Count.ToString(CultureInfo.CurrentCulture);
                if (Items.Count > 0) {
                    string z = GetItemText(Items[0]); 
                    string txt = (z.Length > 40) ? z.Substring(0, 40) : z;
                    s += ", Items[0]: " + txt; 
                } 
            }
            return s; 
        }
        private void UpdateFontCache() {
            fontIsChanged = true;
            integralHeightAdjust = true; 
            try {
                Height = requestedHeight; 
            } 
            finally {
                integralHeightAdjust = false; 
            }
            maxWidth = -1;
            UpdateHorizontalExtent();
            // clear the preferred size cache. 
            CommonProperties.xClearPreferredSizeCache(this);
 
        } 

        private void UpdateHorizontalExtent() { 
            if (!multiColumn && horizontalScrollbar && IsHandleCreated) {
                int width = horizontalExtent;
                if (width == 0) {
                    width = MaxItemWidth; 
                }
                SendMessage(NativeMethods.LB_SETHORIZONTALEXTENT, width, 0); 
            } 
        }
 
        // Updates the cached max item width
        //
        private void UpdateMaxItemWidth(object item, bool removing) {
 
            // We shouldn't be caching maxWidth if we don't have horizontal scrollbars,
            // or horizontal extent has been set 
            // 
            if (!horizontalScrollbar || horizontalExtent > 0) {
                maxWidth = -1; 
                return;
            }

            // Only update if we are currently caching maxWidth 
            //
            if (maxWidth > -1) { 
 
                // Compute item width
                // 
                int width;
                using (Graphics graphics = CreateGraphicsInternal()) {
                    width = (int)(Math.Ceiling(graphics.MeasureString(GetItemText(item), this.Font).Width));
                } 

                if (removing) { 
                    // We're removing this item, so if it's the longest 
                    // in the list, reset the cache
                    // 
                    if (width >= maxWidth) {
                        maxWidth = -1;
                    }
                } 
                else {
                    // We're adding or inserting this item - update the cache 
                    // 
                    if (width > maxWidth) {
                        maxWidth = width; 
                    }
                }
            }
        } 

        // Updates the Custom TabOffsets 
        // 

        private  void UpdateCustomTabOffsets() { 
            if (IsHandleCreated && UseCustomTabOffsets && CustomTabOffsets != null) {
                int wpar = CustomTabOffsets.Count;
                int[] offsets = new int[wpar];
                CustomTabOffsets.CopyTo(offsets, 0); 
                UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.LB_SETTABSTOPS, wpar, offsets);
                Invalidate(); 
            } 
        }
 
        private void WmPrint(ref Message m) {
            base.WndProc(ref m);
            if ((NativeMethods.PRF_NONCLIENT & (int)m.LParam) != 0 && Application.RenderWithVisualStyles && this.BorderStyle == BorderStyle.Fixed3D) {
                IntSecurity.UnmanagedCode.Assert(); 
                try {
                    using (Graphics g = Graphics.FromHdc(m.WParam)) { 
                        Rectangle rect = new Rectangle(0, 0, this.Size.Width - 1, this.Size.Height - 1); 
                        using (Pen pen = new Pen(VisualStyleInformation.TextControlBorder)) {
                            g.DrawRectangle(pen, rect); 
                        }
                        rect.Inflate(-1, -1);
                        g.DrawRectangle(SystemPens.Window, rect);
                    } 
                }
                finally { 
                    CodeAccessPermission.RevertAssert(); 
                }
            } 
        }

        /// 
        ///  
        /// 
        ///  
        [ 
        System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Flags=System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode),
        System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Flags=System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode) 
        ]
        protected virtual void WmReflectCommand(ref Message m) {
            switch (NativeMethods.Util.HIWORD(m.WParam)) {
                case NativeMethods.LBN_SELCHANGE: 
                    if (selectedItems != null) {
                        selectedItems.Dirty(); 
                    } 
                    OnSelectedIndexChanged(EventArgs.Empty);
                    break; 
                case NativeMethods.LBN_DBLCLK:
                    // Handle this inside WM_LBUTTONDBLCLK
                    // OnDoubleClick(EventArgs.Empty);
                    break; 
            }
        } 
 
        /// 
        ///  
        /// 
        /// 
        private void WmReflectDrawItem(ref Message m) {
            NativeMethods.DRAWITEMSTRUCT dis = (NativeMethods.DRAWITEMSTRUCT)m.GetLParam(typeof(NativeMethods.DRAWITEMSTRUCT)); 
            IntPtr dc = dis.hDC;
            IntPtr oldPal = SetUpPalette(dc, false /*force*/, false /*realize*/); 
            try { 
                Graphics g = Graphics.FromHdcInternal(dc);
 
                try {
                    Rectangle bounds = Rectangle.FromLTRB(dis.rcItem.left, dis.rcItem.top, dis.rcItem.right, dis.rcItem.bottom);

                    if (HorizontalScrollbar) { 
                        if (MultiColumn) {
                            bounds.Width = Math.Max(ColumnWidth, bounds.Width); 
                        } 
                        else {
                            bounds.Width = Math.Max(MaxItemWidth, bounds.Width); 
                        }
                    }

 
                    OnDrawItem(new DrawItemEventArgs(g, Font, bounds, dis.itemID, (DrawItemState)dis.itemState, ForeColor, BackColor));
                } 
                finally { 
                    g.Dispose();
                } 
            }
            finally {
                if (oldPal != IntPtr.Zero) {
                    SafeNativeMethods.SelectPalette(new HandleRef(null, dc), new HandleRef(null, oldPal), 0); 
                }
            } 
            m.Result = (IntPtr)1; 
        }
 
        /// 
        /// 
        /// 
        ///  
        // This method is only called if in owner draw mode
        private void WmReflectMeasureItem(ref Message m) { 
 
            NativeMethods.MEASUREITEMSTRUCT mis = (NativeMethods.MEASUREITEMSTRUCT)m.GetLParam(typeof(NativeMethods.MEASUREITEMSTRUCT));
 
            if (drawMode == DrawMode.OwnerDrawVariable && mis.itemID >= 0) {
                Graphics graphics = CreateGraphicsInternal();
                MeasureItemEventArgs mie = new MeasureItemEventArgs(graphics, mis.itemID, ItemHeight);
                try { 
                    OnMeasureItem(mie);
                    mis.itemHeight = mie.ItemHeight; 
                } 
                finally {
                    graphics.Dispose(); 
                }
            }
            else {
                mis.itemHeight = ItemHeight; 
            }
            Marshal.StructureToPtr(mis, m.LParam, false); 
            m.Result = (IntPtr)1; 
        }
 
        /// 
        /// 
        ///     The list's window procedure.  Inheriting classes can override this
        ///     to add extra functionality, but should not forget to call 
        ///     base.wndProc(m); to ensure the list continues to function properly.
        ///  
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] 
        protected override void WndProc(ref Message m) {
            switch (m.Msg) { 
                case NativeMethods.WM_REFLECT + NativeMethods.WM_COMMAND:
                    WmReflectCommand(ref m);
                    break;
                case NativeMethods.WM_REFLECT + NativeMethods.WM_DRAWITEM: 
                    WmReflectDrawItem(ref m);
                    break; 
                case NativeMethods.WM_REFLECT + NativeMethods.WM_MEASUREITEM: 
                    WmReflectMeasureItem(ref m);
                    break; 
                case NativeMethods.WM_PRINT:
                    WmPrint(ref m);
                    break;
                case NativeMethods.WM_LBUTTONDOWN: 
                    if (selectedItems != null) {
                        selectedItems.Dirty(); 
                    } 
                    base.WndProc(ref m);
                    break; 
                case NativeMethods.WM_LBUTTONUP:
                    // Get the mouse location
                    //
                    int x = NativeMethods.Util.SignedLOWORD(m.LParam); 
                    int y = NativeMethods.Util.SignedHIWORD(m.LParam);
                    Point pt = new Point(x,y); 
                    pt = PointToScreen(pt); 
                    bool captured = Capture;
                    if (captured && UnsafeNativeMethods.WindowFromPoint(pt.X, pt.Y) == Handle) { 


                        if (!doubleClickFired && !ValidationCancelled) {
                             OnClick(new MouseEventArgs(MouseButtons.Left, 1, NativeMethods.Util.SignedLOWORD(m.LParam), NativeMethods.Util.SignedHIWORD(m.LParam), 0)); 
                             OnMouseClick(new MouseEventArgs(MouseButtons.Left, 1, NativeMethods.Util.SignedLOWORD(m.LParam), NativeMethods.Util.SignedHIWORD(m.LParam), 0));
 
                        } 
                        else {
                            doubleClickFired = false; 
                            // WM_COMMAND is only fired if the user double clicks an item,
                            // so we can't use that as a double-click substitute
                            if (!ValidationCancelled) {
                                OnDoubleClick(new MouseEventArgs(MouseButtons.Left, 2, NativeMethods.Util.SignedLOWORD(m.LParam), NativeMethods.Util.SignedHIWORD(m.LParam), 0)); 
                                OnMouseDoubleClick(new MouseEventArgs(MouseButtons.Left, 2, NativeMethods.Util.SignedLOWORD(m.LParam), NativeMethods.Util.SignedHIWORD(m.LParam), 0));
 
                            } 
                       }
                    } 

                    //
                    // If this control has been disposed in the user's event handler, then we need to ignore the WM_LBUTTONUP
                    // message to avoid exceptions thrown as a result of handle re-creation (VSWhidbey#95150). 
                    // We handle this situation here and not at the top of the window procedure since this is the only place
                    // where we can get disposed as an effect of external code (form.Close() for instance) and then pass the 
                    // message to the base class. 
                    //
                    if (GetState(STATE_DISPOSED)) 
                    {
                        base.DefWndProc(ref m);
                    }
                    else 
                    {
                        base.WndProc(ref m); 
                    } 

                    doubleClickFired = false; 
                    break;

                case NativeMethods.WM_RBUTTONUP:
                    // Get the mouse location 
                    //
                    int rx = NativeMethods.Util.SignedLOWORD(m.LParam); 
                    int ry = NativeMethods.Util.SignedHIWORD(m.LParam); 
                    Point rpt = new Point(rx,ry);
                    rpt = PointToScreen(rpt); 
                    bool rCaptured = Capture;
                    if (rCaptured && UnsafeNativeMethods.WindowFromPoint(rpt.X, rpt.Y) == Handle) {
                        if (selectedItems != null) {
                            selectedItems.Dirty(); 
                        }
                    } 
                    base.WndProc(ref m); 
                    break;
 
                case NativeMethods.WM_LBUTTONDBLCLK:
                    //the Listbox gets  WM_LBUTTONDOWN - WM_LBUTTONUP -WM_LBUTTONDBLCLK - WM_LBUTTONUP...
                    //sequence for doubleclick...
                    //the first WM_LBUTTONUP, resets the flag for Doubleclick 
                    //So its necessary for us to set it again...
                    doubleClickFired = true; 
                    base.WndProc(ref m); 
                    break;
 
                case NativeMethods.WM_WINDOWPOSCHANGED:
                    base.WndProc(ref m);
                    if (integralHeight && fontIsChanged) {
                        Height = Math.Max(Height,ItemHeight); 
                        fontIsChanged = false;
                    } 
                    break; 

                default: 
                    base.WndProc(ref m);
                    break;
            }
        } 

        ///  
        ///     This is similar to ArrayList except that it also 
        ///     mantains a bit-flag based state element for each item
        ///     in the array. 
        ///
        ///     The methods to enumerate, count and get data support
        ///     virtualized indexes.  Indexes are virtualized according
        ///     to the state mask passed in.  This allows ItemArray 
        ///     to be the backing store for one read-write "master"
        ///     collection and serveral read-only collections based 
        ///     on masks.  ItemArray supports up to 31 masks. 
        /// 
        internal class ItemArray : IComparer { 

            private static int lastMask = 1;

            private ListControl listControl; 
            private Entry[]     entries;
            private int         count; 
            private int         version; 

            public ItemArray(ListControl listControl) { 
                this.listControl = listControl;
            }

            ///  
            ///     The version of this array.  This number changes with each
            ///     change to the item list. 
            ///  
            public int Version {
                get { 
                    return version;
                }
            }
 
            /// 
            ///     Adds the given item to the array.  The state is initially 
            ///     zero. 
            /// 
            public object Add(object item) { 
                EnsureSpace(1);
                version++;
                entries[count] = new Entry(item);
                return entries[count++]; 
            }
 
            ///  
            ///     Adds the given collection of items to the array.
            ///  
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
            public void AddRange(ICollection items) {
                if (items == null) {
                    throw new ArgumentNullException("items"); 
                }
                EnsureSpace(items.Count); 
                foreach(object i in items) { 
                    entries[count++] = new Entry(i);
                } 
                version++;
            }

            ///  
            ///     Clears this array.
            ///  
            public void Clear() { 
                count = 0;
                version++; 
            }

            /// 
            ///     Allocates a new bitmask for use. 
            /// 
            public static int CreateMask() { 
                int mask = lastMask; 
                lastMask = lastMask << 1;
                Debug.Assert(lastMask > mask, "We have overflowed our state mask."); 
                return mask;
            }

            ///  
            ///     Ensures that our internal array has space for
            ///     the requested # of elements. 
            ///  
            private void EnsureSpace(int elements) {
                if (entries == null) { 
                    entries = new Entry[Math.Max(elements, 4)];
                }
                else if (count + elements >= entries.Length) {
                    int newLength = Math.Max(entries.Length * 2, entries.Length + elements); 
                    Entry[] newEntries = new Entry[newLength];
                    entries.CopyTo(newEntries, 0); 
                    entries = newEntries; 
                }
            } 

            /// 
            ///     Turns a virtual index into an actual index.
            ///  
            public int GetActualIndex(int virtualIndex, int stateMask) {
                if (stateMask == 0) { 
                    return virtualIndex; 
                }
 
                // More complex; we must compute this index.
                int calcIndex = -1;
                for(int i = 0; i < count; i++) {
                    if ((entries[i].state & stateMask) != 0) { 
                        calcIndex++;
                        if (calcIndex == virtualIndex) { 
                            return i; 
                        }
                    } 
                }

                return -1;
            } 

            ///  
            ///     Gets the count of items matching the given mask. 
            /// 
            public int GetCount(int stateMask) { 
                // If mask is zero, then just give the main count
                if (stateMask == 0) {
                    return count;
                } 

                // more complex:  must provide a count of items 
                // based on a mask. 

                int filteredCount = 0; 

                for(int i = 0; i < count; i++) {
                    if ((entries[i].state & stateMask) != 0) {
                        filteredCount++; 
                    }
                } 
 
                return filteredCount;
            } 

            /// 
            ///     Retrieves an enumerator that will enumerate based on
            ///     the given mask. 
            /// 
            public IEnumerator GetEnumerator(int stateMask) { 
                return GetEnumerator(stateMask, false); 
            }
 
            /// 
            ///     Retrieves an enumerator that will enumerate based on
            ///     the given mask.
            ///  
            public IEnumerator GetEnumerator(int stateMask, bool anyBit) {
                return new EntryEnumerator(this, stateMask, anyBit); 
            } 

            ///  
            ///     Gets the item at the given index.  The index is
            ///     virtualized against the given mask value.
            /// 
            public object GetItem(int virtualIndex, int stateMask) { 
                int actualIndex = GetActualIndex(virtualIndex, stateMask);
 
                if (actualIndex == -1) { 
                    throw new IndexOutOfRangeException();
                } 

                return entries[actualIndex].item;
            }
            ///  
            ///     Gets the item at the given index.  The index is
            ///     virtualized against the given mask value. 
            ///  
            internal object GetEntryObject(int virtualIndex, int stateMask) {
                int actualIndex = GetActualIndex(virtualIndex, stateMask); 

                if (actualIndex == -1) {
                    throw new IndexOutOfRangeException();
                } 

                return entries[actualIndex]; 
            } 
            /// 
            ///     Returns true if the requested state mask is set. 
            ///     The index is the actual index to the array.
            /// 
            public bool GetState(int index, int stateMask) {
                return ((entries[index].state & stateMask) == stateMask); 
            }
 
            ///  
            ///     Returns the virtual index of the item based on the
            ///     state mask. 
            /// 
            public int IndexOf(object item, int stateMask) {

                int virtualIndex = -1; 

                for(int i = 0; i < count; i++) { 
                    if (stateMask == 0 || (entries[i].state & stateMask) != 0) { 
                        virtualIndex++;
                        if (entries[i].item.Equals(item)) { 
                            return virtualIndex;
                        }
                    }
                } 

                return -1; 
            } 

            ///  
            ///     Returns the virtual index of the item based on the
            ///     state mask. Uses reference equality to identify the
            ///     given object in the list.
            ///  
            public int IndexOfIdentifier(object identifier, int stateMask) {
                int virtualIndex = -1; 
 
                for(int i = 0; i < count; i++) {
                    if (stateMask == 0 || (entries[i].state & stateMask) != 0) { 
                        virtualIndex++;
                        if (entries[i] == identifier) {
                            return virtualIndex;
                        } 
                    }
                } 
 
                return -1;
            } 

            /// 
            ///     Inserts item at the given index.  The index
            ///     is not virtualized. 
            /// 
            public void Insert(int index, object item) { 
                EnsureSpace(1); 

                if (index < count) { 
                    System.Array.Copy(entries, index, entries, index + 1, count - index);
                }

                entries[index] = new Entry(item); 
                count++;
                version++; 
            } 

            ///  
            ///     Removes the given item from the array.  If
            ///     the item is not in the array, this does nothing.
            /// 
            public void Remove(object item) { 
                int index = IndexOf(item, 0);
 
                if (index != -1) { 
                    RemoveAt(index);
                } 
            }

            /// 
            ///     Removes the item at the given index. 
            /// 
            public void RemoveAt(int index) { 
                count--; 
                for (int i = index; i < count; i++) {
                    entries[i] = entries[i+1]; 
                }
                entries[count] = null;
                version++;
            } 

            ///  
            ///     Sets the item at the given index to a new value. 
            /// 
            public void SetItem(int index, object item) { 
                entries[index].item = item;
            }

            ///  
            ///     Sets the state data for the given index.
            ///  
            public void SetState(int index, int stateMask, bool value) { 
                if (value) {
                    entries[index].state |= stateMask; 
                }
                else {
                    entries[index].state &= ~stateMask;
                } 
                version++;
            } 
 
            /// 
            ///     Find element in sorted array. If element is not found returns a binary complement of index for inserting 
            /// 
            public int BinarySearch(object element)
            {
                return Array.BinarySearch(entries, 0, count, element, this); 
            }
 
 
            /// 
            ///     Sorts our array. 
            /// 
            public void Sort() {
                Array.Sort(entries, 0, count, this);
            } 

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 
            public void Sort(Array externalArray) { 
                Array.Sort(externalArray, this);
            } 

            int IComparer.Compare(object item1, object item2) {
                if (item1 == null) {
                    if (item2 == null) 
                        return 0; //both null, then they are equal
 
                    return -1; //item1 is null, but item2 is valid (greater) 
                }
                if (item2 == null) 
                    return 1; //item2 is null, so item 1 is greater

                if (item1 is Entry) {
                    item1 = ((Entry)item1).item; 
                }
 
                if (item2 is Entry) { 
                    item2 = ((Entry)item2).item;
                } 

                String itemName1 = listControl.GetItemText(item1);
                String itemName2 = listControl.GetItemText(item2);
 
                CompareInfo compInfo = (Application.CurrentCulture).CompareInfo;
                return compInfo.Compare(itemName1, itemName2, CompareOptions.StringSort); 
            } 

            ///  
            ///     This is a single entry in our item array.
            /// 
            private class Entry {
                public object item; 
                public int state;
 
                public Entry(object item) { 
                    this.item = item;
                    this.state = 0; 
                }
            }

            ///  
            ///     EntryEnumerator is an enumerator that will enumerate over
            ///     a given state mask. 
            ///  
            private class EntryEnumerator : IEnumerator {
                private ItemArray items; 
                private bool anyBit;
                private int state;
                private int current;
                private int version; 

                ///  
                ///     Creates a new enumerator that will enumerate over the given state. 
                /// 
                public EntryEnumerator(ItemArray items, int state, bool anyBit) { 
                    this.items = items;
                    this.state = state;
                    this.anyBit = anyBit;
                    this.version = items.version; 
                    this.current = -1;
                } 
 
                /// 
                ///     Moves to the next element, or returns false if at the end. 
                /// 
                bool IEnumerator.MoveNext() {
                    if(version != items.version) throw new InvalidOperationException(SR.GetString(SR.ListEnumVersionMismatch));
 
                    while(true) {
                        if (current < items.count - 1) { 
                                            current++; 
                            if (anyBit) {
                                if ((items.entries[current].state & state) != 0) { 
                                    return true;
                                }
                            }
                            else { 
                                if ((items.entries[current].state & state) == state) {
                                    return true; 
                                } 
                            }
                        } 
                        else {
                            current = items.count;
                            return false;
                        } 
                    }
                } 
 
                /// 
                ///     Resets the enumeration back to the beginning. 
                /// 
                void IEnumerator.Reset() {
                    if(version != items.version) throw new InvalidOperationException(SR.GetString(SR.ListEnumVersionMismatch));
                    current = -1; 
                }
 
                ///  
                ///     Retrieves the current value in the enumerator.
                ///  
                object IEnumerator.Current {
                    get {
                        if (current == -1 || current == items.count) {
                            throw new InvalidOperationException(SR.GetString(SR.ListEnumCurrentOutOfRange)); 
                        }
 
                        return items.entries[current].item; 
                    }
                } 
            }
        }

        // Items 
        /// 
        ///  
        ///      
        ///       A collection that stores objects.
        ///     
        /// 
        [ListBindable(false)]
        public class ObjectCollection : IList {
 
            private ListBox owner;
            private ItemArray items; 
 
            /// 
            ///  
            ///    [To be supplied.]
            /// 
            public ObjectCollection(ListBox owner) {
                this.owner = owner; 
            }
 
            ///  
            /// 
            ///      
            ///       Initializes a new instance of ListBox.ObjectCollection based on another ListBox.ObjectCollection.
            ///    
            /// 
            public ObjectCollection(ListBox owner, ObjectCollection value) { 
                this.owner = owner;
                this.AddRange(value); 
            } 

            ///  
            /// 
            ///     
            ///       Initializes a new instance of ListBox.ObjectCollection containing any array of objects.
            ///     
            /// 
            public ObjectCollection(ListBox owner, object[] value) { 
                this.owner = owner; 
                this.AddRange(value);
            } 

            /// 
            /// 
            ///     Retrieves the number of items. 
            /// 
            public int Count { 
                get { 
                    return InnerArray.GetCount(0);
                } 
            }

            /// 
            ///     Internal access to the actual data store. 
            /// 
            internal ItemArray InnerArray { 
                get { 
                    if (items == null) {
                        items = new ItemArray(owner); 
                    }
                    return items;
                }
            } 

            ///  
            ///  
            object ICollection.SyncRoot {
                get { 
                    return this;
                }
            }
 
            /// 
            ///  
            bool ICollection.IsSynchronized { 
                get {
                    return false; 
                }
            }

            ///  
            /// 
            bool IList.IsFixedSize { 
                get { 
                    return false;
                } 
            }

            /// 
            ///  
            ///    [To be supplied.]
            ///  
            public bool IsReadOnly { 
                get {
                    return false; 
                }
            }

            ///  
            /// 
            ///     Adds an item to the List box. For an unsorted List box, the item is 
            ///     added to the end of the existing list of items. For a sorted List box, 
            ///     the item is inserted into the list according to its sorted position.
            ///     The item's toString() method is called to obtain the string that is 
            ///     displayed in the combo box.
            ///     A SystemException occurs if there is insufficient space available to
            ///     store the new item.
            ///  

            public int Add(object item) 
            { 
                owner.CheckNoDataSource();
                int index = AddInternal(item); 
                owner.UpdateHorizontalExtent();
                return index;
            }
 

            private int AddInternal(object item) 
            { 
                if (item == null)
                { 
                    throw new ArgumentNullException("item");
                }
                int index = -1;
                if (!owner.sorted) 
                {
                    InnerArray.Add(item); 
                } 
                else
                { 
                    if (Count > 0)
                    {
                        index = InnerArray.BinarySearch(item);
                        if (index < 0) 
                        {
                            index = ~index; // getting the index of the first element that is larger than the search value 
                                            //this index will be used for insert 
                        }
                    } 
                    else
                        index = 0;

                    Debug.Assert(index >= 0 && index <= Count, "Wrong index for insert"); 
                    InnerArray.Insert(index, item);
                } 
                bool successful = false; 

                try 
                {
                    if (owner.sorted)
                    {
                        if (owner.IsHandleCreated) 
                        {
                            owner.NativeInsert(index, item); 
                            owner.UpdateMaxItemWidth(item, false); 
                            if (owner.selectedItems != null)
                            { 
                                // VSWhidbey 95187: sorting may throw the LB contents and the selectedItem array out of synch.
                                owner.selectedItems.Dirty();
                            }
                        } 
                    }
                    else 
                    { 
                        index = Count - 1;
                        if (owner.IsHandleCreated) 
                        {
                            owner.NativeAdd(item);
                            owner.UpdateMaxItemWidth(item, false);
                        } 
                    }
                    successful = true; 
                } 
                finally
                { 
                    if (!successful)
                    {
                        InnerArray.Remove(item);
                    } 
                }
 
                return index; 
            }
 

            /// 
            /// 
            int IList.Add(object item) { 
                return Add(item);
            } 
 
            /// 
            ///  
            ///    [To be supplied.]
            /// 
            public void AddRange(ObjectCollection value) {
                owner.CheckNoDataSource(); 
                AddRangeInternal((ICollection)value);
            } 
 
            /// 
            ///  
            ///    [To be supplied.]
            /// 
            public void AddRange(object[] items) {
                owner.CheckNoDataSource(); 
                AddRangeInternal((ICollection)items);
            } 
 
            internal void AddRangeInternal(ICollection items) {
 
                if (items == null)
                {
                    throw new ArgumentNullException("items");
                } 
                owner.BeginUpdate();
                try 
                { 
                    foreach (object item in items)
                    { 
                        // adding items one-by-one for performance
                        // not using sort because after the array is sorted index of each newly added item will need to be found
                        // AddInternal is based on BinarySearch and finds index without any additional cost
                        AddInternal(item); 
                    }
                } 
                finally 
                {
                    owner.UpdateHorizontalExtent(); 
                    owner.EndUpdate();
                }
            }
 
            /// 
            ///  
            ///     Retrieves the item with the specified index. 
            /// 
            [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
            public virtual object this[int index] {
                get {
                    if (index < 0 || index >= InnerArray.GetCount(0)) {
                        throw new ArgumentOutOfRangeException("index", SR.GetString(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); 
                    }
 
                    return InnerArray.GetItem(index, 0); 
                }
                set { 
                    owner.CheckNoDataSource();
                    SetItemInternal(index, value);
                }
            } 

            ///  
            ///  
            ///     Removes all items from the ListBox.
            ///  
            public virtual void Clear() {
                owner.CheckNoDataSource();
                ClearInternal();
            } 

            ///  
            ///     Removes all items from the ListBox.  Bypasses the data source check. 
            /// 
            internal void ClearInternal() { 

                //update the width.. to reset Scrollbars..
                // Clear the selection state.
                // 
                int cnt = owner.Items.Count;
                for (int i = 0; i < cnt; i++) { 
                    owner.UpdateMaxItemWidth(InnerArray.GetItem(i, 0), true); 
                }
 

                if (owner.IsHandleCreated) {
                    owner.NativeClear();
                } 
                InnerArray.Clear();
                owner.maxWidth = -1; 
                owner.UpdateHorizontalExtent(); 
            }
 
            /// 
            /// 
            ///    [To be supplied.]
            ///  
            public bool Contains(object value) {
                return IndexOf(value) != -1; 
            } 

            ///  
            /// 
            ///     Copies the ListBox Items collection to a destination array.
            /// 
            public void CopyTo(object[] destination, int arrayIndex) { 
                int count = InnerArray.GetCount(0);
                for(int i = 0; i < count; i++) { 
                    destination[i + arrayIndex] = InnerArray.GetItem(i, 0); 
                }
            } 

            /// 
            /// 
            void ICollection.CopyTo(Array destination, int index) { 
                int count = InnerArray.GetCount(0);
                for(int i = 0; i < count; i++) { 
                    destination.SetValue(InnerArray.GetItem(i, 0), i + index); 
                }
            } 

            /// 
            /// 
            ///     Returns an enumerator for the ListBox Items collection. 
            /// 
            public IEnumerator GetEnumerator() { 
                return InnerArray.GetEnumerator(0); 
            }
 
            /// 
            /// 
            ///    [To be supplied.]
            ///  
            public int IndexOf(object value) {
                if (value == null) { 
                    throw new ArgumentNullException("value"); 
                }
 
                return InnerArray.IndexOf(value,0);
            }

            ///  
            /// 
            ///    [To be supplied.] 
            ///  
            /// 
            internal int IndexOfIdentifier(object value) { 
                if (value == null) {
                    throw new ArgumentNullException("value");
                }
 
                return InnerArray.IndexOfIdentifier(value,0);
            } 
 
            /// 
            ///  
            ///     Adds an item to the combo box. For an unsorted combo box, the item is
            ///     added to the end of the existing list of items. For a sorted combo box,
            ///     the item is inserted into the list according to its sorted position.
            ///     The item's toString() method is called to obtain the string that is 
            ///     displayed in the combo box.
            ///     A SystemException occurs if there is insufficient space available to 
            ///     store the new item. 
            /// 
            public void Insert(int index, object item) { 
                owner.CheckNoDataSource();

                if (index < 0 || index > InnerArray.GetCount(0)) {
                    throw new ArgumentOutOfRangeException("index", SR.GetString(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); 
                }
 
                if (item == null) { 
                    throw new ArgumentNullException("item");
                } 

                // If the combo box is sorted, then nust treat this like an add
                // because we are going to twiddle the index anyway.
                // 
                if (owner.sorted) {
                    Add(item); 
                } 
                else {
                    InnerArray.Insert(index, item); 
                    if (owner.IsHandleCreated) {

                        bool successful = false;
 
                        try {
                            owner.NativeInsert(index, item); 
                            owner.UpdateMaxItemWidth(item, false); 
                            successful = true;
                        } 
                        finally {
                            if (!successful) {
                                InnerArray.RemoveAt(index);
                            } 
                        }
                    } 
                } 
                owner.UpdateHorizontalExtent();
            } 

            /// 
            /// 
            ///     Removes the given item from the ListBox, provided that it is 
            ///     actually in the list.
            ///  
            public void Remove(object value) { 

                int index = InnerArray.IndexOf(value, 0); 

                if (index != -1) {
                    RemoveAt(index);
                } 
            }
 
            ///  
            /// 
            ///     Removes an item from the ListBox at the given index. 
            /// 
            public void RemoveAt(int index) {
                owner.CheckNoDataSource();
 
                if (index < 0 || index >= InnerArray.GetCount(0)) {
                    throw new ArgumentOutOfRangeException("index", SR.GetString(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture))); 
                } 

                owner.UpdateMaxItemWidth(InnerArray.GetItem(index, 0), true); 

                // VSWhidbey 95181: Update InnerArray before calling NativeRemoveAt to ensure that when
                // SelectedIndexChanged is raised (by NativeRemoveAt), InnerArray's state matches wrapped LB state.
                InnerArray.RemoveAt(index); 

                if (owner.IsHandleCreated) { 
                    owner.NativeRemoveAt(index); 
                }
 
                owner.UpdateHorizontalExtent();
            }

            internal void SetItemInternal(int index, object value) { 
                if (value == null) {
                    throw new ArgumentNullException("value"); 
                } 

                if (index < 0 || index >= InnerArray.GetCount(0)) { 
                    throw new ArgumentOutOfRangeException("index", SR.GetString(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture)));
                }

                owner.UpdateMaxItemWidth(InnerArray.GetItem(index, 0), true); 
                InnerArray.SetItem(index, value);
 
                // If the native control has been created, and the display text of the new list item object 
                // is different to the current text in the native list item, recreate the native list item...
                if (owner.IsHandleCreated) { 
                    bool selected = (owner.SelectedIndex == index);
                    if (String.Compare(this.owner.GetItemText(value), this.owner.NativeGetItemText(index), true, CultureInfo.CurrentCulture) != 0) {
                        owner.NativeRemoveAt(index);
                        owner.SelectedItems.SetSelected(index, false); 
                        owner.NativeInsert(index, value);
                        owner.UpdateMaxItemWidth(value, false); 
                        if (selected) { 
                            owner.SelectedIndex = index;
                        } 
                    }
                    else {
                        // NEW - FOR COMPATIBILITY REASONS
                        // Minimum compatibility fix for VSWhidbey 377287 
                        if (selected) {
                            owner.OnSelectedIndexChanged(EventArgs.Empty); //will fire selectedvaluechanged 
                        } 
                    }
                } 
                owner.UpdateHorizontalExtent();
            }
        } // end ObjectCollection
 
        //*****************************************************************************************
        // IntegerCollection 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        public class IntegerCollection : IList {
            private ListBox owner;
            private int[] innerArray; 
            private int count=0;
 
            ///  
            /// 
            ///    [To be supplied.] 
            /// 
            public IntegerCollection(ListBox owner) {
                this.owner = owner;
            } 

            ///  
            ///  
            ///    Number of current selected items.
            ///  
            [Browsable(false)]
            public int Count {
                get {
                    return count; 
                }
            } 
 
            /// 
            ///  
            object ICollection.SyncRoot {
                get {
                    return this;
                } 
            }
 
            ///  
            /// 
            bool ICollection.IsSynchronized { 
                get {
                    return true;
                }
            } 

            ///  
            ///  
            bool IList.IsFixedSize {
                get { 
                    return false;
                }
            }
 
            /// 
            ///  
            ///    [To be supplied.] 
            /// 
            bool IList.IsReadOnly { 
                get {
                    return false;
                }
            } 

            ///  
            ///  
            ///    [To be supplied.]
            ///  
            public bool Contains(int item) {
                return IndexOf(item) != -1;
            }
 
            /// 
            ///  
            bool IList.Contains(object item) { 
                if (item is Int32) {
                    return Contains((int)item); 
                }
                else {
                    return false;
                } 
            }
 
            public void Clear() 
            {
                count = 0; 
                innerArray = null;
            }

            ///  
            /// 
            ///    [To be supplied.] 
            ///  
            public int IndexOf(int item) {
                int index = -1; 

                if (innerArray != null) {
                    index = Array.IndexOf(innerArray, item);
 
                    // We initialize innerArray with more elements than needed in the method EnsureSpace,
                    // and we don't actually remove element from innerArray in the method RemoveAt, 
                    // so there maybe some elements which are not actually in innerArray will be found 
                    // and we need to filter them out
                    if (index >= count) { 
                        index = -1;
                    }
                }
 
                return index;
            } 
 
            /// 
            ///  
            int IList.IndexOf(object item) {
                if (item is Int32) {
                    return IndexOf((int)item);
                } 
                else {
                    return -1; 
                } 
            }
 

            /// 
            ///     Add a unique integer to the collection in sorted order.
            ///     A SystemException occurs if there is insufficient space available to 
            ///     store the new item.
            ///  
            private int AddInternal(int item) { 

                EnsureSpace(1); 

                int index = IndexOf(item);
                if (index == -1) {
                    innerArray[count++] = item; 
                    Array.Sort(innerArray,0,count);
                    index = IndexOf(item); 
                } 
               return index;
            } 

            /// 
            /// 
            ///     Adds a unique integer to the collection in sorted order. 
            ///     A SystemException occurs if there is insufficient space available to
            ///     store the new item. 
            ///  
            public int Add(int item) {
                int index = AddInternal(item); 
                owner.UpdateCustomTabOffsets();

                return index;
            } 

            ///  
            ///  
            [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")]
            [ 
                SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters") // "item" is the name of the param passed in.
                                                                                                            // So we don't have to localize it.
            ]
            int IList.Add(object item) { 
                if (!(item is int)) {
                    throw new ArgumentException("item"); 
                } 
                return Add((int)item);
            } 

            /// 
            /// 
            ///    [To be supplied.] 
            /// 
            public void AddRange(int[] items) { 
                AddRangeInternal((ICollection)items); 
            }
 
            /// 
            /// 
            ///    [To be supplied.]
            ///  
            public void AddRange(IntegerCollection value) {
                AddRangeInternal((ICollection)value); 
            } 

            ///  
            ///     Add range that bypasses the data source check.
            /// 
            [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")]
            [ 
                SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters") // "item" is the name of the param passed in.
                                                                                                            // So we don't have to localize it. 
            ] 
            private void AddRangeInternal(ICollection items) {
                if (items == null) { 
                    throw new ArgumentNullException("items");
                }
                owner.BeginUpdate();
                try 
                {
                    EnsureSpace(items.Count); 
                    foreach(object item in items) { 
                        if (!(item is int)) {
                            throw new ArgumentException("item"); 
                        }
                        else {
                            AddInternal((int)item);
                        } 
                    }
                    owner.UpdateCustomTabOffsets(); 
                } 
                finally
                { 
                    owner.EndUpdate();
                }
            }
 

            ///  
            ///     Ensures that our internal array has space for 
            ///     the requested # of elements.
            ///  
            private void EnsureSpace(int elements) {
                if (innerArray == null) {
                    innerArray = new int[Math.Max(elements, 4)];
                } 
                else if (count + elements >= innerArray.Length) {
                    int newLength = Math.Max(innerArray.Length * 2, innerArray.Length + elements); 
                    int[] newEntries = new int[newLength]; 
                    innerArray.CopyTo(newEntries, 0);
                    innerArray = newEntries; 
                }
            }

            ///  
            /// 
            void IList.Clear() { 
                Clear(); 
            }
 
            /// 
            /// 
            void IList.Insert(int index, object value) {
                throw new NotSupportedException(SR.GetString(SR.ListBoxCantInsertIntoIntegerCollection)); 
            }
 
            ///  
            /// 
            [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] 
            [
                SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters") // "value" is the name of the param passed in.
                                                                                                            // So we don't have to localize it.
            ] 
            void IList.Remove(object value) {
                if (!(value is int)) { 
                    throw new ArgumentException("value"); 
                }
                Remove((int)value); 
            }

            /// 
            ///  
            void IList.RemoveAt(int index) {
                RemoveAt(index); 
            } 

            ///  
            /// 
            ///     Removes the given item from the array.  If
            ///     the item is not in the array, this does nothing.
            ///  
            public void Remove(int item) {
 
                int index = IndexOf(item); 

                if (index != -1) { 
                    RemoveAt(index);
                }
            }
 
            /// 
            ///  
            ///     Removes the item at the given index. 
            /// 
            public void RemoveAt(int index) { 
                if (index < 0 || index >= count) {
                    throw new ArgumentOutOfRangeException("index", SR.GetString(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture)));
                }
 
                count--;
                for (int i = index; i < count; i++) { 
                    innerArray[i] = innerArray[i+1]; 
                }
            } 

            /// 
            /// 
            ///     Retrieves the specified selected item. 
            /// 
            [ 
                SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters") // "index" is the name of the param passed in. 
                                                                                                            // So we don't have to localize it.
            ] 
            public int this[int index] {
                get {
                    return innerArray[index];
                } 
                [
                    SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")     // This exception already shipped. 
                                                                                                            // We can't change its text. 
                ]
                set { 

                    if (index < 0 || index >= count) {
                        throw new ArgumentOutOfRangeException("index", SR.GetString(SR.InvalidArgument, "index", (index).ToString(CultureInfo.CurrentCulture)));
                    } 
                    innerArray[index] = (int)value;
                    owner.UpdateCustomTabOffsets(); 
 

                } 
            }

            /// 
            ///  
            [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")]
            object IList.this[int index] { 
                get { 
                    return this[index];
                } 
                [
                    SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters"),    // "value" is the name of the param.
                                                                                                                    // So we don't have to localize it.
                    SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")             // This exception already shipped. 
                                                                                                                    // We can't change its text.
                ] 
                set { 
                    if (!(value is int)) {
                        throw new ArgumentException("value"); 
                    }
                    else {
                        this[index] = (int)value;
                    } 

                } 
            } 

            ///  
            /// 
            ///    [To be supplied.]
            /// 
            public void CopyTo(Array destination, int index) { 
                int cnt = Count;
                for (int i = 0; i < cnt; i++) { 
                    destination.SetValue(this[i], i + index); 
                }
            } 

            /// 
            /// 
            ///    [To be supplied.] 
            /// 
            IEnumerator IEnumerable.GetEnumerator() { 
                return new CustomTabOffsetsEnumerator(this); 
            }
 
            /// 
            ///     EntryEnumerator is an enumerator that will enumerate over
            ///     a given state mask.
            ///  
            private class CustomTabOffsetsEnumerator : IEnumerator {
                private IntegerCollection items; 
                private int current; 

                ///  
                ///     Creates a new enumerator that will enumerate over the given state.
                /// 
                public CustomTabOffsetsEnumerator(IntegerCollection items) {
                    this.items = items; 
                    this.current = -1;
                } 
 
                /// 
                ///     Moves to the next element, or returns false if at the end. 
                /// 
                bool IEnumerator.MoveNext() {

                    if (current < items.Count - 1) { 
                        current++;
                        return true; 
                    } 
                    else {
                        current = items.Count; 
                        return false;
                    }
                }
 
                /// 
                ///     Resets the enumeration back to the beginning. 
                ///  
                void IEnumerator.Reset() {
                    current = -1; 
                }

                /// 
                ///     Retrieves the current value in the enumerator. 
                /// 
                object IEnumerator.Current { 
                    get { 
                        if (current == -1 || current == items.Count) {
                            throw new InvalidOperationException(SR.GetString(SR.ListEnumCurrentOutOfRange)); 
                        }

                        return items[current];
                    } 
                }
            } 
        } 

        //***************************************************************************************** 

        // SelectedIndices
        /// 
        ///  
        ///    [To be supplied.]
        ///  
        public class SelectedIndexCollection : IList { 
            private ListBox owner;
 
            /* C#r: protected */
            /// 
            /// 
            ///    [To be supplied.] 
            /// 
            public SelectedIndexCollection(ListBox owner) { 
                this.owner = owner; 
            }
 
            /// 
            /// 
            ///    Number of current selected items.
            ///  
            [Browsable(false)]
            public int Count { 
                get { 
                    return owner.SelectedItems.Count;
                } 
            }

            /// 
            ///  
            object ICollection.SyncRoot {
                get { 
                    return this; 
                }
            } 

            /// 
            /// 
            bool ICollection.IsSynchronized { 
                get {
                    return true; 
                } 
            }
 
            /// 
            /// 
            bool IList.IsFixedSize {
                get { 
                    return true;
                } 
            } 

            ///  
            /// 
            ///    [To be supplied.]
            /// 
            public bool IsReadOnly { 
                get {
                    return true; 
                } 
            }
 
            /// 
            /// 
            ///    [To be supplied.]
            ///  
            public bool Contains(int selectedIndex) {
                return IndexOf(selectedIndex) != -1; 
            } 

            ///  
            /// 
            bool IList.Contains(object selectedIndex) {
                if (selectedIndex is Int32) {
                    return Contains((int)selectedIndex); 
                }
                else { 
                    return false; 
                }
            } 

            /// 
            /// 
            ///    [To be supplied.] 
            /// 
            public int IndexOf(int selectedIndex) { 
 
                // Just what does this do?  The selectedIndex parameter above is the index into the
                // main object collection.  We look at the state of that item, and if the state indicates 
                // that it is selected, we get back the virtualized index into this collection.  Indexes on
                // this collection match those on the SelectedObjectCollection.
                if (selectedIndex >= 0 &&
                    selectedIndex < InnerArray.GetCount(0) && 
                    InnerArray.GetState(selectedIndex, SelectedObjectCollection.SelectedObjectMask)) {
 
                    return InnerArray.IndexOf(InnerArray.GetItem(selectedIndex, 0), SelectedObjectCollection.SelectedObjectMask); 
                }
 
                return -1;
            }

            ///  
            /// 
            int IList.IndexOf(object selectedIndex) { 
                if (selectedIndex is Int32) { 
                    return IndexOf((int)selectedIndex);
                } 
                else {
                    return -1;
                }
            } 

            ///  
            ///  
            int IList.Add(object value) {
                throw new NotSupportedException(SR.GetString(SR.ListBoxSelectedIndexCollectionIsReadOnly)); 
            }

            /// 
            ///  
            void IList.Clear() {
                throw new NotSupportedException(SR.GetString(SR.ListBoxSelectedIndexCollectionIsReadOnly)); 
            } 

            ///  
            /// 
            void IList.Insert(int index, object value) {
                throw new NotSupportedException(SR.GetString(SR.ListBoxSelectedIndexCollectionIsReadOnly));
            } 

            ///  
            ///  
            void IList.Remove(object value) {
                throw new NotSupportedException(SR.GetString(SR.ListBoxSelectedIndexCollectionIsReadOnly)); 
            }

            /// 
            ///  
            void IList.RemoveAt(int index) {
                throw new NotSupportedException(SR.GetString(SR.ListBoxSelectedIndexCollectionIsReadOnly)); 
            } 

            ///  
            /// 
            ///     Retrieves the specified selected item.
            /// 
            public int this[int index] { 
                get {
                    object identifier = InnerArray.GetEntryObject(index, SelectedObjectCollection.SelectedObjectMask); 
                    return InnerArray.IndexOfIdentifier(identifier, 0); 
                }
            } 

            /// 
            /// 
            object IList.this[int index] { 
                get {
                    return this[index]; 
                } 
                set {
                    throw new NotSupportedException(SR.GetString(SR.ListBoxSelectedIndexCollectionIsReadOnly)); 
                }
            }

            ///  
            ///     This is the item array that stores our data.  We share this backing store
            ///     with the main object collection. 
            ///  
            private ItemArray InnerArray {
                get { 
                    owner.SelectedItems.EnsureUpToDate();
                    return ((ObjectCollection)owner.Items).InnerArray;
                }
            } 

            ///  
            ///  
            ///    [To be supplied.]
            ///  
            public void CopyTo(Array destination, int index) {
                int cnt = Count;
                for (int i = 0; i < cnt; i++) {
                    destination.SetValue(this[i], i + index); 
                }
            } 
 
            /// 
            ///  
            ///    [To be supplied.]
            /// 
            public void Clear() {
                if (owner != null) { 
                    owner.ClearSelected();
                } 
            } 

            ///  
            /// 
            ///    [To be supplied.]
            /// 
            public void Add(int index) { 
                if (owner != null) {
                    ObjectCollection items = owner.Items; 
                    if (items != null) { 
                        if (index != -1 && !Contains(index)) {
                            owner.SetSelected(index, true); 
                        }
                    }
                }
            } 

            ///  
            ///  
            ///    [To be supplied.]
            ///  
            public void Remove(int index) {
                if (owner != null) {
                    ObjectCollection items = owner.Items;
                    if (items != null) { 
                        if (index != -1 && Contains(index)) {
                            owner.SetSelected(index, false); 
                        } 
                    }
                } 
            }

            /// 
            ///  
            ///    [To be supplied.]
            ///  
            public IEnumerator GetEnumerator() { 
                return new SelectedIndexEnumerator(this);
            } 

            /// 
            ///     EntryEnumerator is an enumerator that will enumerate over
            ///     a given state mask. 
            /// 
            private class SelectedIndexEnumerator : IEnumerator { 
                private SelectedIndexCollection items; 
                private int current;
 
                /// 
                ///     Creates a new enumerator that will enumerate over the given state.
                /// 
                public SelectedIndexEnumerator(SelectedIndexCollection items) { 
                    this.items = items;
                    this.current = -1; 
                } 

                ///  
                ///     Moves to the next element, or returns false if at the end.
                /// 
                bool IEnumerator.MoveNext() {
 
                    if (current < items.Count - 1) {
                        current++; 
                        return true; 
                    }
                    else { 
                        current = items.Count;
                        return false;
                    }
                } 

                ///  
                ///     Resets the enumeration back to the beginning. 
                /// 
                void IEnumerator.Reset() { 
                    current = -1;
                }

                ///  
                ///     Retrieves the current value in the enumerator.
                ///  
                object IEnumerator.Current { 
                    get {
                        if (current == -1 || current == items.Count) { 
                            throw new InvalidOperationException(SR.GetString(SR.ListEnumCurrentOutOfRange));
                        }

                        return items[current]; 
                    }
                } 
            } 
        }
 
        // Should be "ObjectCollection", except we already have one of those.
        /// 
        /// 
        ///    [To be supplied.] 
        /// 
        public class SelectedObjectCollection : IList { 
 
            // This is the bitmask used within ItemArray to identify selected objects.
            internal static int SelectedObjectMask = ItemArray.CreateMask(); 

            private ListBox owner;
            private bool    stateDirty;
            private int     lastVersion; 
            private int     count;
 
            /* C#r: protected */ 
            /// 
            ///  
            ///    [To be supplied.]
            /// 
            public SelectedObjectCollection(ListBox owner) {
                this.owner = owner; 
                this.stateDirty = true;
                this.lastVersion = -1; 
            } 

            ///  
            /// 
            ///     Number of current selected items.
            /// 
            public int Count { 
                get {
                    if (owner.IsHandleCreated) { 
                        SelectionMode current = (owner.selectionModeChanging) ? owner.cachedSelectionMode : owner.selectionMode; 
                        switch (current) {
 
                            case SelectionMode.None:
                                return 0;

                            case SelectionMode.One: 
                                int index = owner.SelectedIndex;
                                if (index >= 0) { 
                                    return 1; 
                                }
                                return 0; 

                            case SelectionMode.MultiSimple:
                            case SelectionMode.MultiExtended:
                                return unchecked( (int) (long)owner.SendMessage(NativeMethods.LB_GETSELCOUNT, 0, 0)); 
                        }
 
                        return 0; 
                    }
 
                    // If the handle hasn't been created, we must do this the hard way.
                    // Getting the count when using a mask is expensive, so cache it.
                    //
                    if (lastVersion != InnerArray.Version) { 
                        lastVersion = InnerArray.Version;
                        count = InnerArray.GetCount(SelectedObjectMask); 
                    } 

                    return count; 
                }
            }

            ///  
            /// 
            object ICollection.SyncRoot { 
                get { 
                    return this;
                } 
            }

            /// 
            ///  
            bool ICollection.IsSynchronized {
                get { 
                    return false; 
                }
            } 

            /// 
            /// 
            bool IList.IsFixedSize { 
                get {
                    return true; 
                } 
            }
 
            /// 
            ///     Called by the list box to dirty the selected item state.
            /// 
            internal void Dirty() { 
                stateDirty = true;
            } 
 
            /// 
            ///     This is the item array that stores our data.  We share this backing store 
            ///     with the main object collection.
            /// 
            private ItemArray InnerArray {
                get { 
                    EnsureUpToDate();
                    return ((ObjectCollection)owner.Items).InnerArray; 
                } 
            }
 

            /// 
            ///     This is the function that Ensures that the selections are uptodate with
            ///     current listbox handle selections. 
            /// 
            internal void EnsureUpToDate() { 
                if (stateDirty) { 
                     stateDirty = false;
                     if (owner.IsHandleCreated) { 
                         owner.NativeUpdateSelection();
                     }
                }
            } 

 
            ///  
            /// 
            ///    [To be supplied.] 
            /// 
            public bool IsReadOnly {
                get {
                    return true; 
                }
            } 
 
            /// 
            ///  
            ///    [To be supplied.]
            /// 
            public bool Contains(object selectedObject) {
                return IndexOf(selectedObject) != -1; 
            }
 
            ///  
            /// 
            ///    [To be supplied.] 
            /// 
            public int IndexOf(object selectedObject) {
                return InnerArray.IndexOf(selectedObject, SelectedObjectMask);
            } 

            ///  
            ///  
            int IList.Add(object value) {
                throw new NotSupportedException(SR.GetString(SR.ListBoxSelectedObjectCollectionIsReadOnly)); 
            }

            /// 
            ///  
            void IList.Clear() {
                throw new NotSupportedException(SR.GetString(SR.ListBoxSelectedObjectCollectionIsReadOnly)); 
            } 

            ///  
            /// 
            void IList.Insert(int index, object value) {
                throw new NotSupportedException(SR.GetString(SR.ListBoxSelectedObjectCollectionIsReadOnly));
            } 

            ///  
            ///  
            void IList.Remove(object value) {
                throw new NotSupportedException(SR.GetString(SR.ListBoxSelectedObjectCollectionIsReadOnly)); 
            }

            /// 
            ///  
            void IList.RemoveAt(int index) {
                throw new NotSupportedException(SR.GetString(SR.ListBoxSelectedObjectCollectionIsReadOnly)); 
            } 

            // A new internal method used in SelectedIndex getter... 
            // For a Multi select ListBox there can be two items with the same name ...
            // and hence a object comparison is required...
            // This method returns the "object" at the passed index rather than the "item" ...
            // this "object" is then compared in the IndexOf( ) method of the itemsCollection. 
            //
            ///  
            ///  
            internal object GetObjectAt(int index) {
               return InnerArray.GetEntryObject(index, SelectedObjectCollection.SelectedObjectMask); 
            }

            /// 
            ///  
            ///     Retrieves the specified selected item.
            ///  
            [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
            public object this[int index] {
                get { 
                    return InnerArray.GetItem(index, SelectedObjectMask);
                }
                set {
                    throw new NotSupportedException(SR.GetString(SR.ListBoxSelectedObjectCollectionIsReadOnly)); 
                }
            } 
 
            /// 
            ///  
            ///    [To be supplied.]
            /// 
            public void CopyTo(Array destination, int index) {
                int cnt = InnerArray.GetCount(SelectedObjectMask); 
                for (int i = 0; i < cnt; i++) {
                    destination.SetValue(InnerArray.GetItem(i, SelectedObjectMask), i + index); 
                } 
            }
 
            /// 
            /// 
            ///    [To be supplied.]
            ///  
            public IEnumerator GetEnumerator() {
                return InnerArray.GetEnumerator(SelectedObjectMask); 
            } 

            ///  
            ///     This method returns if the actual item index is selected.  The index is the index to the MAIN
            ///     collection, not this one.
            /// 
            internal bool GetSelected(int index) { 
                return InnerArray.GetState(index, SelectedObjectMask);
            } 
 
            // when SelectedObjectsCollection::ItemArray is accessed we push the selection from Native ListBox into our .Net ListBox - see EnsureUpToDate()
            // when we create the handle we need to be able to do the opposite : push the selection from .Net ListBox into Native ListBox 
            internal void PushSelectionIntoNativeListBox(int index) {
                // we can't use ItemArray accessor because this will wipe out our Selection collection
                bool selected = ((ObjectCollection)owner.Items).InnerArray.GetState(index, SelectedObjectMask);
                // push selection only if the item is actually selected 
                // this also takes care of the case where owner.SelectionMode == SelectionMode.One
                if (selected) { 
                    this.owner.NativeSetSelected(index, true /*we signal selection to the native listBox only if the item is actually selected*/); 
                }
            } 

            /// 
            ///     Same thing for GetSelected.
            ///  
            internal void SetSelected(int index, bool value) {
                InnerArray.SetState(index, SelectedObjectMask, value); 
            } 

            ///  
            /// 
            ///    [To be supplied.]
            /// 
            public void Clear() { 
                if (owner != null) {
                    owner.ClearSelected(); 
                } 
            }
 
            /// 
            /// 
            ///    [To be supplied.]
            ///  
            public void Add(object value)  {
                if (owner != null) { 
                    ObjectCollection items = owner.Items; 
                    if (items != null && value != null) {
                        int index = items.IndexOf(value); 
                        if (index != -1 && !GetSelected(index)) {
                            owner.SelectedIndex = index;
                        }
                    } 
                }
            } 
 
            /// 
            ///  
            ///    [To be supplied.]
            /// 
            public void Remove(object value) {
                if (owner != null) { 
                    ObjectCollection items = owner.Items;
                    if (items != null & value != null) { 
                        int index = items.IndexOf(value); 
                        if (index != -1 && GetSelected(index)) {
                            owner.SetSelected(index, false); 
                        }
                    }
                }
            } 
        }
    } 
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK