| File: System\Windows\Forms\Controls\WebBrowser\HtmlElementCollection.cs | Web Access |
| Project: src\winforms\src\System.Windows.Forms\System.Windows.Forms.csproj (System.Windows.Forms) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; using Windows.Win32.System.Com; using Windows.Win32.System.Variant; using Windows.Win32.Web.MsHtml; namespace System.Windows.Forms; public sealed unsafe class HtmlElementCollection : ICollection { private readonly AgileComPointer<IHTMLElementCollection>? _htmlElementCollection; private readonly HtmlElement[]? _elementsArray; private readonly HtmlShimManager _shimManager; internal HtmlElementCollection(HtmlShimManager shimManager) { _htmlElementCollection = null; _elementsArray = null; _shimManager = shimManager; } internal HtmlElementCollection(HtmlShimManager shimManager, IHTMLElementCollection* elements) { #if DEBUG _htmlElementCollection = new(elements, takeOwnership: true, trackDisposal: false); #else _htmlElementCollection = new(elements, takeOwnership: true); #endif _elementsArray = null; _shimManager = shimManager; Debug.Assert(NativeHtmlElementCollection is not null, "The element collection object should implement IHTMLElementCollection"); } internal HtmlElementCollection(HtmlShimManager shimManager, HtmlElement[] array) { _htmlElementCollection = null; _elementsArray = array; _shimManager = shimManager; } private AgileComPointer<IHTMLElementCollection>? NativeHtmlElementCollection => _htmlElementCollection; public HtmlElement? this[int index] { get { // do some bounds checking here... ArgumentOutOfRangeException.ThrowIfNegative(index); ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(index, Count); if (NativeHtmlElementCollection is not null) { using var htmlElementCollection = NativeHtmlElementCollection.GetInterface(); using ComScope<IDispatch> dispatch = new(null); htmlElementCollection.Value->item((VARIANT)index, (VARIANT)0, dispatch).ThrowOnFailure(); IHTMLElement* htmlElement; return !dispatch.IsNull && dispatch.Value->QueryInterface(IID.Get<IHTMLElement>(), (void**)&htmlElement).Succeeded ? new HtmlElement(_shimManager, htmlElement) : null; } return _elementsArray?[index]; } } public HtmlElement? this[string elementId] { get { if (NativeHtmlElementCollection is not null) { using var nativeHtmlElementCollection = NativeHtmlElementCollection.GetInterface(); using var variantElementId = (VARIANT)elementId; using ComScope<IDispatch> dispatch = new(null); nativeHtmlElementCollection.Value->item(variantElementId, (VARIANT)0, dispatch).ThrowOnFailure(); IHTMLElement* htmlElement; return !dispatch.IsNull && dispatch.Value->QueryInterface(IID.Get<IHTMLElement>(), (void**)&htmlElement).Succeeded ? new(_shimManager, htmlElement) : null; } else if (_elementsArray is not null) { int count = _elementsArray.Length; for (int i = 0; i < count; i++) { HtmlElement element = _elementsArray[i]; if (element.Id == elementId) { return element; } } return null; // not found } else { return null; } } } public HtmlElementCollection GetElementsByName(string name) { int count = Count; HtmlElement[] temp = new HtmlElement[count]; // count is the maximum # of matches int tempIndex = 0; for (int i = 0; i < count; i++) { HtmlElement element = this[i]!; if (element.GetAttribute("name") == name) { temp[tempIndex] = element; tempIndex++; } } if (tempIndex == 0) { return new HtmlElementCollection(_shimManager); } else { HtmlElement[] elements = new HtmlElement[tempIndex]; for (int i = 0; i < tempIndex; i++) { elements[i] = temp[i]; } return new HtmlElementCollection(_shimManager, elements); } } /// <summary> /// Returns the total number of elements in the collection. /// </summary> public int Count { get { if (NativeHtmlElementCollection is not null) { using var nativeHtmlElementCollection = NativeHtmlElementCollection.GetInterface(); int length; nativeHtmlElementCollection.Value->get_length(&length).ThrowOnFailure(); return length; } return _elementsArray is not null ? _elementsArray.Length : 0; } } bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; void ICollection.CopyTo(Array dest, int index) { int count = Count; for (int i = 0; i < count; i++) { dest.SetValue(this[i], index++); } } public IEnumerator GetEnumerator() { HtmlElement[] htmlElements = new HtmlElement[Count]; ((ICollection)this).CopyTo(htmlElements, 0); return htmlElements.GetEnumerator(); } }