/*internal bool StandardValuesQueried { * get { * this.standardValuesQueried = value; * } * } */ // ensure that we have processed the caStructs into arrays // of values and strings // private void EnsureArrays() { if (this.arraysFetched) { return; } this.arraysFetched = true; try { // marshal the items. object[] nameItems = nameMarshaller.Items; object[] cookieItems = valueMarshaller.Items; NativeMethods.IPerPropertyBrowsing ppb = (NativeMethods.IPerPropertyBrowsing)target.TargetObject; int itemCount = 0; Debug.Assert(cookieItems != null && nameItems != null, "An item array is null"); if (nameItems.Length > 0) { object[] valueItems = new object[cookieItems.Length]; NativeMethods.VARIANT var = new NativeMethods.VARIANT(); int cookie; Debug.Assert(cookieItems.Length == nameItems.Length, "Got uneven names and cookies"); // for each name item, we ask the object for it's corresponding value. // Type targetType = target.PropertyType; for (int i = nameItems.Length - 1; i >= 0; i--) { cookie = (int)cookieItems[i]; if (nameItems[i] == null || !(nameItems[i] is string)) { Debug.Fail("Bad IPerPropertyBrowsing item [" + i.ToString(CultureInfo.InvariantCulture) + "], name=" + (nameItems == null ? "(unknown)" : nameItems[i].ToString())); continue; } var.vt = (short)NativeMethods.tagVT.VT_EMPTY; int hr = ppb.GetPredefinedValue(target.DISPID, cookie, var); if (hr == NativeMethods.S_OK && var.vt != (short)NativeMethods.tagVT.VT_EMPTY) { valueItems[i] = var.ToObject(); if (valueItems[i].GetType() != targetType) { if (targetType.IsEnum) { valueItems[i] = Enum.ToObject(targetType, valueItems[i]); } else { try { valueItems[i] = Convert.ChangeType(valueItems[i], targetType, CultureInfo.InvariantCulture); } catch { // oh well... } } } } var.Clear(); if (hr == NativeMethods.S_OK) { itemCount++; continue; } else if (itemCount > 0) { // shorten the arrays to ignore the failed ones. this isn't terribly // efficient but shouldn't happen very often. It's rare for these to fail. // Array.Copy(nameItems, i, nameItems, i + 1, itemCount); Array.Copy(valueItems, i, valueItems, i + 1, itemCount); } } // pass this data down to the base Com2Enum object... string[] strings = new string[itemCount]; Array.Copy(nameItems, 0, strings, 0, itemCount); base.PopulateArrays(strings, valueItems); } } catch (Exception ex) { base.PopulateArrays(new string[0], new object[0]); Debug.Fail("Failed to build IPerPropertyBrowsing editor. " + ex.GetType().Name + ", " + ex.Message); } }
internal static bool GetSuggestions(object textSegmentHandle, ArrayList suggestions) { ITextSegment textSegment = (ITextSegment)textSegmentHandle; UnsafeNativeMethods.IEnumVariant variantEnumerator; textSegment.get_Suggestions(out variantEnumerator); if (variantEnumerator == null) { // nl6 will return null enum instead of an empty enum. return false; } bool hasSuggestions = false; try { NativeMethods.VARIANT variant = new NativeMethods.VARIANT(); int[] fetched = new int[1]; while (true) { int result; variant.Clear(); result = EnumVariantNext(variantEnumerator, variant, fetched); if (result != NativeMethods.S_OK) break; if (fetched[0] == 0) break; hasSuggestions = true; if (suggestions != null) { // Convert the VARIANT to string, and add it to our list. // There's some special magic here. The VARIANT is VT_UI2/ByRef. // But under the hood it's really a raw WCHAR *. suggestions.Add(Marshal.PtrToStringUni(variant.data1.Value)); } else { // Caller just wants to know if any suggestions are // available, no need to iterate further. break; } } } finally { Marshal.ReleaseComObject(variantEnumerator); } return hasSuggestions; }
/*internal bool StandardValuesQueried { get { this.standardValuesQueried = value; } } */ // ensure that we have processed the caStructs into arrays // of values and strings // private void EnsureArrays() { if (this.arraysFetched) { return; } this.arraysFetched = true; try { // marshal the items. object[] nameItems = nameMarshaller.Items; object[] cookieItems= valueMarshaller.Items; NativeMethods.IPerPropertyBrowsing ppb = (NativeMethods.IPerPropertyBrowsing)target.TargetObject; int itemCount = 0; Debug.Assert(cookieItems != null && nameItems != null, "An item array is null"); if (nameItems.Length > 0){ object[] valueItems = new object[cookieItems.Length]; NativeMethods.VARIANT var = new NativeMethods.VARIANT(); int cookie; Debug.Assert(cookieItems.Length == nameItems.Length, "Got uneven names and cookies"); // for each name item, we ask the object for it's corresponding value. // Type targetType = target.PropertyType; for (int i = nameItems.Length - 1; i >= 0; i--) { cookie = (int)cookieItems[i]; if (nameItems[i] == null || !(nameItems[i] is string)) { Debug.Fail("Bad IPerPropertyBrowsing item [" + i.ToString(CultureInfo.InvariantCulture) + "], name=" + (nameItems == null ? "(unknown)" : nameItems[i].ToString())); continue; } var.vt = (short)NativeMethods.tagVT.VT_EMPTY; int hr = ppb.GetPredefinedValue(target.DISPID, cookie, var); if (hr == NativeMethods.S_OK && var.vt != (short)NativeMethods.tagVT.VT_EMPTY) { valueItems[i] = var.ToObject(); if (valueItems[i].GetType() != targetType) { if (targetType.IsEnum) { valueItems[i] = Enum.ToObject(targetType, valueItems[i]); } else { try { valueItems[i] = Convert.ChangeType(valueItems[i], targetType, CultureInfo.InvariantCulture); } catch { // oh well... } } } } var.Clear(); if (hr == NativeMethods.S_OK) { itemCount++; continue; } else if (itemCount > 0){ // shorten the arrays to ignore the failed ones. this isn't terribly // efficient but shouldn't happen very often. It's rare for these to fail. // Array.Copy(nameItems, i, nameItems, i+1, itemCount); Array.Copy(valueItems, i, valueItems, i+1, itemCount); } } // pass this data down to the base Com2Enum object... string[] strings = new string[itemCount]; Array.Copy(nameItems, 0, strings, 0, itemCount); base.PopulateArrays(strings, valueItems); } } catch (Exception ex) { base.PopulateArrays(new string[0], new object[0]); Debug.Fail("Failed to build IPerPropertyBrowsing editor. " + ex.GetType().Name + ", " + ex.Message); } }
internal int EnumTextSegments(char[] text, int count, EnumSentencesCallback sentenceCallback, EnumTextSegmentsCallback segmentCallback, object data) { int segmentCount = 0; // Unintuively, the speller engine will grab and store the pointer // we pass into ITextChunk.SetInputArray. So it's not safe to merely // pinvoke text directly. We need to allocate a chunk of memory // and keep it fixed for the duration of this method call. IntPtr inputArray = Marshal.AllocHGlobal(count * 2); try { // Give the TextChunk its next block of text. Marshal.Copy(text, 0, inputArray, count); _textChunk.SetInputArray(inputArray, count); // // Iterate over sentences. // UnsafeNativeMethods.IEnumVariant sentenceEnumerator; // Note because we're in the engine's ReuseObjects mode, we may // not use ITextChunk.get_Sentences. We must use the enumerator. _textChunk.GetEnumerator(out sentenceEnumerator); try { NativeMethods.VARIANT variant = new NativeMethods.VARIANT(); int[] fetched = new int[1]; bool continueIteration = true; sentenceEnumerator.Reset(); do { int result; variant.Clear(); result = EnumVariantNext(sentenceEnumerator, variant, fetched); if (result != NativeMethods.S_OK) break; if (fetched[0] == 0) break; SpellerInterop.ISentence sentence = (SpellerInterop.ISentence)variant.ToObject(); try { int sentenceSegmentCount; sentence.get_Count(out sentenceSegmentCount); segmentCount += sentenceSegmentCount; if (segmentCallback != null) { // // Iterate over segments. // for (int i = 0; continueIteration && i < sentenceSegmentCount; i++) { SpellerInterop.ITextSegment textSegment; // Do a callback for this ITextSegment. sentence.get_Item(i, out textSegment); try { if (!segmentCallback(textSegment, data)) { continueIteration = false; } } finally { Marshal.ReleaseComObject(textSegment); } } } // Make another callback when we're done with the entire sentence. if (sentenceCallback != null) { continueIteration = sentenceCallback(sentence, data); } } finally { Marshal.ReleaseComObject(sentence); } } while (continueIteration); variant.Clear(); } finally { Marshal.ReleaseComObject(sentenceEnumerator); } } finally { Marshal.FreeHGlobal(inputArray); } return segmentCount; }