private NativeMethods.IPerPropertyBrowsing GetPerPropertyBrowsing() { if (iPerPropertyBrowsing == null && !axState[checkedIppb] && instance != null) { axState[checkedIppb] = true; if (instance is NativeMethods.IPerPropertyBrowsing) { iPerPropertyBrowsing = (NativeMethods.IPerPropertyBrowsing) instance; } } return iPerPropertyBrowsing; }
/*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); } }
private void ReleaseAxControl() { // This line is like a bit of magic... // sometimes, we crash with it on, // sometimes, with it off... // Lately, I have decided to leave it on... // (oh, yes, and the crashes seemed to disappear...) //cpr: ComLib.Release(instance); this.NoComponentChangeEvents++; ContainerControl f = ContainingControl; if (f != null) { f.VisibleChanged -= this.onContainerVisibleChanged; } try { if (instance != null) { Marshal.FinalReleaseComObject(instance); instance = null; iOleInPlaceObject = null; iOleObject = null; iOleControl = null; iOleInPlaceActiveObject = null; iOleInPlaceActiveObjectExternal = null; iPerPropertyBrowsing = null; iCategorizeProperties = null; iPersistStream = null; iPersistStreamInit = null; iPersistStorage = null; } axState[checkedIppb] = false; axState[checkedCP] = false; axState[disposed] = true; freezeCount = 0; axState[sinkAttached] = false; wndprocAddr = IntPtr.Zero; SetOcState(OC_PASSIVE); } finally { this.NoComponentChangeEvents--; } }
private void OnGetTypeConverterAndTypeEditor(Com2PropertyDescriptor sender, GetTypeConverterAndTypeEditorEvent gveevent) { if (sender.TargetObject is NativeMethods.IPerPropertyBrowsing) { NativeMethods.IPerPropertyBrowsing ppb = (NativeMethods.IPerPropertyBrowsing)sender.TargetObject; bool hasStrings = false; // check for enums NativeMethods.CA_STRUCT caStrings = new NativeMethods.CA_STRUCT(); NativeMethods.CA_STRUCT caCookies = new NativeMethods.CA_STRUCT(); int hr = NativeMethods.S_OK; try { hr = ppb.GetPredefinedStrings(sender.DISPID, caStrings, caCookies); } catch (ExternalException ex) { hr = ex.ErrorCode; Debug.Fail("An exception occurred inside IPerPropertyBrowsing::GetPredefinedStrings(dispid=" + sender.DISPID + "), object type=" + new ComNativeDescriptor().GetClassName(ppb) + ". This is caused by an exception (usually an AV) inside the object being browsed, and is not a problem in the properties window."); } // Terminate the existing editor if we created the current one // so if the items have disappeared, we don't hold onto the old // items. if (gveevent.TypeConverter is Com2IPerPropertyEnumConverter) { gveevent.TypeConverter = null; } if (hr != NativeMethods.S_OK) { hasStrings = false; } else { hasStrings = true; } if (hasStrings) { OleStrCAMarshaler stringMarshaler = new OleStrCAMarshaler(caStrings); Int32CAMarshaler intMarshaler = new Int32CAMarshaler(caCookies); if (stringMarshaler.Count > 0 && intMarshaler.Count > 0) { gveevent.TypeConverter = new Com2IPerPropertyEnumConverter(new Com2IPerPropertyBrowsingEnum(sender, this, stringMarshaler, intMarshaler, true)); } else { //hasStrings = false; } } // if we didn't get any strings, try the proppage edtior // if (!hasStrings) { // this is a _bit_ of a backwards-compat work around... // many older ActiveX controls will show a property page // for all properties since the old grid would only put up the // [...] button for "(Custom)". If we have a conversion editor, // don't allow this to override it... // if (sender.ConvertingNativeType) { return; } Guid g = GetPropertyPageGuid(ppb, sender.DISPID); if (!Guid.Empty.Equals(g)) { gveevent.TypeEditor = new Com2PropertyPageUITypeEditor(sender, g, (UITypeEditor)gveevent.TypeEditor); } } } }