|
//------------------------------------------------------------------------------
// <copyright file="AxHost.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
/*
*/
namespace System.Windows.Forms {
using Microsoft.Win32;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Configuration.Assemblies;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Design;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Remoting;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Windows.Forms.ComponentModel;
using System.Windows.Forms.ComponentModel.Com2Interop;
using System.Windows.Forms.Design;
using System.Runtime.Versioning;
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost"]/*' />
/// <devdoc>
/// <para>
///
/// Wraps ActiveX controls and exposes them as
/// fully featured windows forms controls.
/// </para>
/// </devdoc>
[
ComVisible(true),
ClassInterface(ClassInterfaceType.AutoDispatch),
ToolboxItem(false),
DesignTimeVisible(false),
DefaultEvent("Enter"),
Designer("System.Windows.Forms.Design.AxHostDesigner, " + AssemblyRef.SystemDesign),
PermissionSet(SecurityAction.LinkDemand, Name="FullTrust"),
PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust")
]
public abstract class AxHost : Control, ISupportInitialize, ICustomTypeDescriptor {
private static TraceSwitch AxHTraceSwitch = new TraceSwitch("AxHTrace", "ActiveX handle tracing");
private static TraceSwitch AxPropTraceSwitch = new TraceSwitch("AxPropTrace", "ActiveX property tracing");
private static TraceSwitch AxHostSwitch = new TraceSwitch("AxHost", "ActiveX host creation");
private static BooleanSwitch AxIgnoreTMSwitch = new BooleanSwitch("AxIgnoreTM", "ActiveX switch to ignore thread models");
private static BooleanSwitch AxAlwaysSaveSwitch = new BooleanSwitch("AxAlwaysSave", "ActiveX to save all controls regardless of their IsDirty function return value");
/// <devdoc>
/// Flags which may be passed to the AxHost constructor
/// </devdoc>
[SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")]
internal class AxFlags {
/// <devdoc>
/// Indicates that the context menu for the control should not contain an
/// "Edit" verb unless the activeX controls itself decides to proffer it.
/// By default, all wrapped activeX controls will contain an edit verb.
/// </devdoc>
internal const int PreventEditMode = 0x1;
/// <devdoc>
/// Indicated that the context menu for the control should contain
/// a "Properties..." verb which may be used to show the property
/// pages for the control. Note that even if this flag is
/// specified, the verb will not appear unless the control
/// proffers a set of property pages.
/// [Since most activeX controls alreay have their own properties verb
/// on the context menu, the default is not to include one specified by
/// this flag.]
/// </devdoc>
internal const int IncludePropertiesVerb = 0x2;
/// <devdoc>
/// </devdoc>
/// <internalonly/>
internal const int IgnoreThreadModel = 0x10000000;
}
private static COMException E_NOTIMPL = new COMException(SR.GetString(SR.AXNotImplemented), unchecked((int)0x80000001));
private static COMException E_INVALIDARG = new COMException(SR.GetString(SR.AXInvalidArgument), unchecked((int)0x80070057));
private static COMException E_FAIL = new COMException(SR.GetString(SR.AXUnknownError), unchecked((int)0x80004005));
private static COMException E_NOINTERFACE = new COMException(SR.GetString(SR.AxInterfaceNotSupported), unchecked((int)0x80004002));
private const int INPROC_SERVER = 1;
private const int OC_PASSIVE = 0;
private const int OC_LOADED = 1; // handler, but no server [ocx created]
private const int OC_RUNNING = 2; // server running, invisible [iqa & depersistance]
private const int OC_INPLACE = 4; // server in-place active [inplace]
private const int OC_UIACTIVE = 8;// server is UI active [uiactive]
private const int OC_OPEN = 16; // server is being open edited [not used]
private const int EDITM_NONE = 0; // object not being edited
private const int EDITM_OBJECT = 1; // object provided an edit verb and we invoked it
private const int EDITM_HOST = 2; // we invoked our own edit verb
private const int STG_UNKNOWN = -1;
private const int STG_STREAM = 0;
private const int STG_STREAMINIT = 1;
private const int STG_STORAGE = 2;
private const int OLEIVERB_SHOW = -1;
private const int OLEIVERB_HIDE = -3;
private const int OLEIVERB_UIACTIVATE = -4;
private const int OLEIVERB_INPLACEACTIVATE =-5;
private const int OLEIVERB_PROPERTIES = -7;
private const int OLEIVERB_PRIMARY = 0;
private readonly int REGMSG_MSG = SafeNativeMethods.RegisterWindowMessage(Application.WindowMessagesVersion + "_subclassCheck");
private const int REGMSG_RETVAL = 123;
private static int logPixelsX = -1;
private static int logPixelsY = -1;
private static Guid icf2_Guid = typeof(UnsafeNativeMethods.IClassFactory2).GUID;
private static Guid ifont_Guid = typeof(UnsafeNativeMethods.IFont).GUID;
private static Guid ifontDisp_Guid = typeof(SafeNativeMethods.IFontDisp).GUID;
private static Guid ipicture_Guid = typeof(UnsafeNativeMethods.IPicture).GUID;
private static Guid ipictureDisp_Guid = typeof(UnsafeNativeMethods.IPictureDisp).GUID;
private static Guid ivbformat_Guid = typeof(UnsafeNativeMethods.IVBFormat).GUID;
private static Guid ioleobject_Guid = typeof(UnsafeNativeMethods.IOleObject).GUID;
private static Guid dataSource_Guid = new Guid("{7C0FFAB3-CD84-11D0-949A-00A0C91110ED}");
private static Guid windowsMediaPlayer_Clsid = new Guid("{22d6f312-b0f6-11d0-94ab-0080c74c7e95}");
private static Guid comctlImageCombo_Clsid = new Guid("{a98a24c0-b06f-3684-8c12-c52ae341e0bc}");
private static Guid maskEdit_Clsid = new Guid("{c932ba85-4374-101b-a56c-00aa003668dc}");
// Static state for perf optimization
//
private static Hashtable fontTable;
// BitVector32 masks for various internal state flags.
//
private static readonly int ocxStateSet = BitVector32.CreateMask();
private static readonly int editorRefresh = BitVector32.CreateMask(ocxStateSet);
private static readonly int listeningToIdle = BitVector32.CreateMask(editorRefresh);
private static readonly int refreshProperties = BitVector32.CreateMask(listeningToIdle);
private static readonly int checkedIppb = BitVector32.CreateMask(refreshProperties);
private static readonly int checkedCP = BitVector32.CreateMask(checkedIppb);
private static readonly int fNeedOwnWindow = BitVector32.CreateMask(checkedCP);
private static readonly int fOwnWindow = BitVector32.CreateMask(fNeedOwnWindow);
private static readonly int fSimpleFrame = BitVector32.CreateMask(fOwnWindow);
private static readonly int fFakingWindow = BitVector32.CreateMask(fSimpleFrame);
private static readonly int rejectSelection = BitVector32.CreateMask(fFakingWindow);
private static readonly int ownDisposing = BitVector32.CreateMask(rejectSelection);
private static readonly int sinkAttached = BitVector32.CreateMask(ownDisposing);
private static readonly int disposed = BitVector32.CreateMask(sinkAttached);
private static readonly int manualUpdate = BitVector32.CreateMask(disposed);
private static readonly int addedSelectionHandler = BitVector32.CreateMask(manualUpdate);
private static readonly int valueChanged = BitVector32.CreateMask(addedSelectionHandler);
private static readonly int handlePosRectChanged = BitVector32.CreateMask(valueChanged);
private static readonly int siteProcessedInputKey = BitVector32.CreateMask(handlePosRectChanged);
private static readonly int needLicenseKey = BitVector32.CreateMask(siteProcessedInputKey);
private static readonly int inTransition = BitVector32.CreateMask(needLicenseKey);
private static readonly int processingKeyUp = BitVector32.CreateMask(inTransition);
private static readonly int assignUniqueID = BitVector32.CreateMask(processingKeyUp);
private static readonly int renameEventHooked = BitVector32.CreateMask(assignUniqueID);
private BitVector32 axState = new BitVector32();
private int storageType = STG_UNKNOWN;
private int ocState = OC_PASSIVE;
private int miscStatusBits;
private int freezeCount = 0;
private int flags = 0;
private int selectionStyle = 0;
private int editMode = EDITM_NONE;
private int noComponentChange = 0;
private IntPtr wndprocAddr = IntPtr.Zero;
private Guid clsid;
private string text = "";
private string licenseKey = null;
private readonly OleInterfaces oleSite;
private AxComponentEditor editor;
private AxContainer container;
private ContainerControl containingControl;
private ContainerControl newParent;
private AxContainer axContainer;
private State ocxState;
private IntPtr hwndFocus = IntPtr.Zero;
// CustomTypeDescriptor related state
//
private Hashtable properties = null;
private Hashtable propertyInfos = null;
private PropertyDescriptorCollection propsStash = null;
private Attribute[] attribsStash = null;
// interface pointers to the ocx
//
private Object instance;
private UnsafeNativeMethods.IOleInPlaceObject iOleInPlaceObject;
private UnsafeNativeMethods.IOleObject iOleObject;
private UnsafeNativeMethods.IOleControl iOleControl;
private UnsafeNativeMethods.IOleInPlaceActiveObject iOleInPlaceActiveObject;
private UnsafeNativeMethods.IOleInPlaceActiveObject iOleInPlaceActiveObjectExternal;
private NativeMethods.IPerPropertyBrowsing iPerPropertyBrowsing;
private NativeMethods.ICategorizeProperties iCategorizeProperties;
private UnsafeNativeMethods.IPersistPropertyBag iPersistPropBag;
private UnsafeNativeMethods.IPersistStream iPersistStream;
private UnsafeNativeMethods.IPersistStreamInit iPersistStreamInit;
private UnsafeNativeMethods.IPersistStorage iPersistStorage;
private AboutBoxDelegate aboutBoxDelegate = null;
private EventHandler selectionChangeHandler;
private bool isMaskEdit;
private bool ignoreDialogKeys;
private EventHandler onContainerVisibleChanged;
// These should be in the order given by the PROPCAT_X values
// Also, note that they are not to be localized...
private static CategoryAttribute[] categoryNames = new CategoryAttribute [] {
null,
new WinCategoryAttribute("Default"),
new WinCategoryAttribute("Default"),
new WinCategoryAttribute("Font"),
new WinCategoryAttribute("Layout"),
new WinCategoryAttribute("Appearance"),
new WinCategoryAttribute("Behavior"),
new WinCategoryAttribute("Data"),
new WinCategoryAttribute("List"),
new WinCategoryAttribute("Text"),
new WinCategoryAttribute("Scale"),
new WinCategoryAttribute("DDE")
};
private Hashtable objectDefinedCategoryNames = null; // Integer -> String
#if DEBUG
static AxHost() {
Debug.Assert((int)DockStyle.None == (int)NativeMethods.ActiveX.ALIGN_NO_CHANGE,"align value mismatch");
Debug.Assert((int)DockStyle.Top == (int)NativeMethods.ActiveX.ALIGN_TOP,"align value mismatch");
Debug.Assert((int)DockStyle.Bottom == (int)NativeMethods.ActiveX.ALIGN_BOTTOM,"align value mismatch");
Debug.Assert((int)DockStyle.Left == (int)NativeMethods.ActiveX.ALIGN_LEFT,"align value mismatch");
Debug.Assert((int)DockStyle.Right == (int)NativeMethods.ActiveX.ALIGN_RIGHT,"align value mismatch");
Debug.Assert((int)MouseButtons.Left == 0x00100000, "mb.left mismatch");
Debug.Assert((int)MouseButtons.Right == 0x00200000, "mb.right mismatch");
Debug.Assert((int)MouseButtons.Middle == 0x00400000, "mb.middle mismatch");
Debug.Assert((int)Keys.Shift == 0x00010000, "key.shift mismatch");
Debug.Assert((int)Keys.Control == 0x00020000, "key.control mismatch");
Debug.Assert((int)Keys.Alt == 0x00040000, "key.alt mismatch");
}
#endif
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxHost1"]/*' />
/// <devdoc>
/// Creates a new instance of a control which wraps an activeX control given by the
/// clsid parameter and flags of 0.
/// </devdoc>
protected AxHost(string clsid) : this(clsid, 0) {
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxHost2"]/*' />
/// <devdoc>
/// <para>Creates a new instance of a control which wraps an activeX control given by the
/// clsid and flags parameters.</para>
/// </devdoc>
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
protected AxHost(string clsid, int flags) : base() {
if (Application.OleRequired() != ApartmentState.STA) {
throw new ThreadStateException(SR.GetString(SR.AXMTAThread, clsid));
}
this.oleSite = new OleInterfaces(this);
this.selectionChangeHandler = new EventHandler(this.OnNewSelection);
this.clsid = new Guid(clsid);
this.flags = flags;
this.axState[assignUniqueID] = !this.GetType().GUID.Equals(comctlImageCombo_Clsid);
this.axState[needLicenseKey] = true;
this.axState[rejectSelection] = true;
isMaskEdit = this.clsid.Equals(AxHost.maskEdit_Clsid);
this.onContainerVisibleChanged = new EventHandler(this.OnContainerVisibleChanged);
}
private bool CanUIActivate {
get {
return IsUserMode() || editMode != EDITM_NONE;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.CreateParams"]/*' />
/// <devdoc>
/// Returns the CreateParams used to create the handle for this control.
/// </devdoc>
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
if (axState[fOwnWindow] && IsUserMode()) {
cp.Style = cp.Style & (~NativeMethods.WS_VISIBLE);
}
return cp;
}
}
private bool GetAxState(int mask) {
return this.axState[mask];
}
private void SetAxState(int mask, bool value) {
this.axState[mask] = value;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AttachInterfaces"]/*' />
/// <devdoc>
/// AxHost will call this when it is ready to create the underlying ActiveX object.
/// Wrappers will override this and cast the pointer obtained by calling getOcx() to
/// their own interfaces. getOcx() should not usually be called before this function.
/// Note: calling begin will result in a call to this function.
/// </devdoc>
protected virtual void AttachInterfaces() {
}
private void RealizeStyles() {
SetStyle(ControlStyles.UserPaint, false);
int bits = 0;
int hr = GetOleObject().GetMiscStatus(NativeMethods.ActiveX.DVASPECT_CONTENT, out bits);
if (!NativeMethods.Failed(hr)) {
miscStatusBits = bits;
ParseMiscBits(miscStatusBits);
}
}
// Control overrides:
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.BackColor"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public override Color BackColor {
get {
return base.BackColor;
}
set {
base.BackColor = value;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.BackgroundImage"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override Image BackgroundImage {
get {
return base.BackgroundImage;
}
set {
base.BackgroundImage = value;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.BackgroundImageLayout"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override ImageLayout BackgroundImageLayout {
get {
return base.BackgroundImageLayout;
}
set {
base.BackgroundImageLayout = value;
}
}
/// <devdoc>
/// <para>Hide ImeMode: it doesn't make sense for this control</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
new public ImeMode ImeMode
{
get
{
return base.ImeMode;
}
set
{
base.ImeMode = value;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.MouseClick"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler MouseClick {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "MouseClick"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.MouseDoubleClick"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler MouseDoubleClick {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "MouseDoubleClick"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.Cursor"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public override Cursor Cursor {
get {
return base.Cursor;
}
set {
base.Cursor = value;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ContextMenu"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public override ContextMenu ContextMenu {
get {
return base.ContextMenu;
}
set {
base.ContextMenu = value;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.DefaultSize"]/*' />
/// <devdoc>
/// Deriving classes can override this to configure a default size for their control.
/// This is more efficient than setting the size in the control's constructor.
/// </devdoc>
protected override Size DefaultSize {
get {
return new Size(75, 23);
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.Enabled"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public virtual new bool Enabled {
get {
return base.Enabled;
}
set {
base.Enabled = value;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.Font"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public override Font Font {
get {
return base.Font;
}
set {
base.Font = value;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ForeColor"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public override Color ForeColor {
get {
return base.ForeColor;
}
set {
base.ForeColor = value;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.RightToLeft"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[
Browsable(false),
EditorBrowsable(EditorBrowsableState.Never),
Localizable(true)
]
public new virtual bool RightToLeft {
get {
RightToLeft rtol = base.RightToLeft;
return rtol == System.Windows.Forms.RightToLeft.Yes;
}
set {
base.RightToLeft = (value) ? System.Windows.Forms.RightToLeft.Yes : System.Windows.Forms.RightToLeft.No;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.Text"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public override string Text {
get {
return text;
}
set {
text = value;
}
}
internal override bool CanAccessProperties {
get {
int ocState = GetOcState();
return(axState[fOwnWindow] &&
(ocState > OC_RUNNING || (IsUserMode() && ocState >= OC_RUNNING)) ||
ocState >= OC_INPLACE);
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.PropsValid"]/*' />
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected bool PropsValid() {
return CanAccessProperties;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.BeginInit"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public void BeginInit() {
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.EndInit"]/*' />
/// <devdoc>
/// Signals the object that loading of all peer components and property
/// sets are complete.
/// It should be possible to invoke any property get or set after calling this method.
/// Note that a sideeffect of this method is the creation of the parent control's
/// handle, therefore, this control must be parented before begin is called
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public void EndInit() {
if (ParentInternal != null) {
ParentInternal.CreateControl(true);
ContainerControl f = ContainingControl;
if (f != null) {
f.VisibleChanged += this.onContainerVisibleChanged;
}
}
}
private void OnContainerVisibleChanged(object sender, EventArgs e) {
ContainerControl f = ContainingControl;
if (f != null) {
if (f.Visible && Visible && !axState[fOwnWindow]) {
MakeVisibleWithShow();
}
else if (!f.Visible && Visible && IsHandleCreated && GetOcState() >= OC_INPLACE) {
HideAxControl();
}
else if (f.Visible && !GetState(STATE_VISIBLE) && IsHandleCreated && GetOcState() >= OC_INPLACE) {
HideAxControl();
}
}
}
//
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.EditMode"]/*' />
/// <devdoc>
/// Determines if the control is in edit mode.
/// </devdoc>
[ Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public bool EditMode {
get {
return editMode != EDITM_NONE;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.HasAboutBox"]/*' />
/// <devdoc>
/// Determines if this control has an about box.
/// </devdoc>
[ Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public bool HasAboutBox {
get {
return aboutBoxDelegate != null;
}
}
private int NoComponentChangeEvents {
get {
return noComponentChange;
}
set {
noComponentChange = value;
}
}
//
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ShowAboutBox"]/*' />
/// <devdoc>
/// Shows the about box for this control.
/// </devdoc>
public void ShowAboutBox() {
if (aboutBoxDelegate != null) {
aboutBoxDelegate();
}
}
//
/// <devdoc>
/// Retrieves the OCX control flags.
/// </devdoc>
#if false
// FxCop: Currently not used
[ Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
private int OcxFlags {
get {
return flags;
}
}
#endif
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.BackColorChanged"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler BackColorChanged {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "BackColorChanged"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.BackgroundImageChanged"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler BackgroundImageChanged {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "BackgroundImageChanged"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.BackgroundImageLayoutChanged"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler BackgroundImageLayoutChanged {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "BackgroundImageLayoutChanged"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.BindingContextChanged"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler BindingContextChanged {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "BindingContextChanged"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ContextMenuChanged"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler ContextMenuChanged {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "ContextMenuChanged"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.CursorChanged"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler CursorChanged {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "CursorChanged"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.EnabledChanged"]/*' />
/// <devdoc>
/// <para>Occurs when the control is enabled.</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler EnabledChanged {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "EnabledChanged"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.FontChanged"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler FontChanged {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "FontChanged"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ForeColorChanged"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler ForeColorChanged {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "ForeColorChanged"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.RightToLeftChanged"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler RightToLeftChanged {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "RightToLeftChanged"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.TextChanged"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler TextChanged {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "TextChanged"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.Click"]/*' />
/// <devdoc>
/// <para>Occurs when the control is clicked.</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler Click {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "Click"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.DragDrop"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event DragEventHandler DragDrop {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "DragDrop"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.DragEnter"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event DragEventHandler DragEnter {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "DragEnter"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.DragOver"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event DragEventHandler DragOver {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "DragOver"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.DragLeave"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler DragLeave {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "DragLeave"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GiveFeedback"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event GiveFeedbackEventHandler GiveFeedback {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "GiveFeedback"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.HelpRequested"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event HelpEventHandler HelpRequested {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "HelpRequested"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.Paint"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event PaintEventHandler Paint {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "Paint"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.QueryContinueDrag"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event QueryContinueDragEventHandler QueryContinueDrag {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "QueryContinueDrag"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.QueryAccessibilityHelp"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event QueryAccessibilityHelpEventHandler QueryAccessibilityHelp {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "QueryAccessibilityHelp"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.DoubleClick"]/*' />
/// <devdoc>
/// <para>Occurs when the control is double clicked.</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler DoubleClick {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "DoubleClick"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ImeModeChanged"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler ImeModeChanged {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "ImeModeChanged"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.KeyDown"]/*' />
/// <devdoc>
/// <para>Occurs when a key is pressed down while the control has focus.</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event KeyEventHandler KeyDown {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "KeyDown"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.KeyPress"]/*' />
/// <devdoc>
/// <para> Occurs when a key is pressed while the control has focus.</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event KeyPressEventHandler KeyPress {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "KeyPress"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.KeyUp"]/*' />
/// <devdoc>
/// <para> Occurs when a key is released while the control has focus.</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event KeyEventHandler KeyUp {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "KeyUp"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.Layout"]/*' />
/// <devdoc>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event LayoutEventHandler Layout {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "Layout"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.MouseDown"]/*' />
/// <devdoc>
/// <para>Occurs when the mouse pointer is over the control and a mouse button is
/// pressed.</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event MouseEventHandler MouseDown {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "MouseDown"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.MouseEnter"]/*' />
/// <devdoc>
/// <para> Occurs when the mouse pointer enters the AxHost.</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler MouseEnter {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "MouseEnter"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.MouseLeave"]/*' />
/// <devdoc>
/// <para> Occurs when the mouse pointer leaves the AxHost.</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler MouseLeave {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "MouseLeave"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.MouseHover"]/*' />
/// <devdoc>
/// <para> Occurs when the mouse pointer hovers over the contro.</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler MouseHover {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "MouseHover"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.MouseMove"]/*' />
/// <devdoc>
/// <para> Occurs when the mouse pointer is moved over the AxHost.</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event MouseEventHandler MouseMove {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "MouseMove"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.MouseUp"]/*' />
/// <devdoc>
/// <para>Occurs when the mouse pointer is over the control and a mouse button is released.</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event MouseEventHandler MouseUp {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "MouseUp"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.MouseWheel"]/*' />
/// <devdoc>
/// <para> Occurs when the mouse wheel moves while the control has focus.</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event MouseEventHandler MouseWheel {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "MouseWheel"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ChangeUICues"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event UICuesEventHandler ChangeUICues {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "ChangeUICues"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.StyleChanged"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler StyleChanged {
add {
throw new NotSupportedException(SR.GetString(SR.AXAddInvalidEvent, "StyleChanged"));
}
remove {
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.OnFontChanged"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
protected override void OnFontChanged(EventArgs e) {
base.OnFontChanged(e);
AmbientChanged(NativeMethods.ActiveX.DISPID_AMBIENT_FONT);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.OnForeColorChanged"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
protected override void OnForeColorChanged(EventArgs e) {
base.OnForeColorChanged(e);
AmbientChanged(NativeMethods.ActiveX.DISPID_AMBIENT_FORECOLOR);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.OnBackColorChanged"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
protected override void OnBackColorChanged(EventArgs e) {
base.OnBackColorChanged(e);
AmbientChanged(NativeMethods.ActiveX.DISPID_AMBIENT_BACKCOLOR);
}
private void AmbientChanged(int dispid) {
if (GetOcx() != null) {
try {
Invalidate();
GetOleControl().OnAmbientPropertyChange(dispid);
}
catch (Exception t) {
Debug.Fail(t.ToString());
}
}
}
private bool OwnWindow() {
return axState[fOwnWindow] || axState[fFakingWindow];
}
private IntPtr GetHandleNoCreate() {
if (IsHandleCreated) return Handle;
return IntPtr.Zero;
}
private ISelectionService GetSelectionService() {
return GetSelectionService(this);
}
private static ISelectionService GetSelectionService(Control ctl) {
ISite site = ctl.Site;
if (site != null) {
Object o = site.GetService(typeof(ISelectionService));
Debug.Assert(o == null || o is ISelectionService, "service must implement ISelectionService");
//Note: if o is null, we want to return null anyway. Happy day.
return o as ISelectionService;
}
return null;
}
private void AddSelectionHandler() {
if (axState[addedSelectionHandler]) return;
ISelectionService iss = GetSelectionService();
if (iss != null) {
iss.SelectionChanging += selectionChangeHandler;
}
axState[addedSelectionHandler] = true;
}
private void OnComponentRename(object sender, ComponentRenameEventArgs e)
{
// When we're notified of a rename, see if this is the componnent that is being
// renamed.
//
if (e.Component == this)
{
// if it is, call DISPID_AMBIENT_DISPLAYNAME directly on the
// control itself.
//
UnsafeNativeMethods.IOleControl oleCtl = this.GetOcx() as UnsafeNativeMethods.IOleControl;
if (oleCtl != null)
{
oleCtl.OnAmbientPropertyChange(NativeMethods.ActiveX.DISPID_AMBIENT_DISPLAYNAME);
}
}
}
private bool RemoveSelectionHandler() {
if (!axState[addedSelectionHandler]) return false;
ISelectionService iss = GetSelectionService();
if (iss != null) {
iss.SelectionChanging -= selectionChangeHandler;
}
axState[addedSelectionHandler] = false;
return true;
}
private void SyncRenameNotification(bool hook) {
if (DesignMode && hook != axState[renameEventHooked])
{
// if we're in design mode, listen to the following events from the component change service
//
IComponentChangeService changeService = (IComponentChangeService)GetService(typeof(IComponentChangeService));
if (changeService != null)
{
if (hook) {
changeService.ComponentRename += new ComponentRenameEventHandler(OnComponentRename);
}
else {
changeService.ComponentRename -= new ComponentRenameEventHandler(OnComponentRename);
}
axState[renameEventHooked] = hook;
}
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.Site"]/*' />
/// <devdoc>
/// Sets the site of this component. A non-null value indicates that the
/// component has been added to a container, and a null value indicates that
/// the component is being removed from a container.
/// </devdoc>
public override ISite Site {
set {
// If we are disposed then just return.
if (axState[disposed])
{
return;
}
bool reAddHandler = RemoveSelectionHandler();
bool olduMode = IsUserMode();
// clear the old hook
//
SyncRenameNotification(false);
base.Site = value;
bool newuMode = IsUserMode();
if (!newuMode) GetOcxCreate();
if (reAddHandler) AddSelectionHandler();
SyncRenameNotification(value != null);
// For inherited forms we create the OCX first in User mode
// and then we get sited. At that time, we have to re-activate
// the OCX by transitioning down to and up to the current state.
//
if (value != null && !newuMode && olduMode != newuMode && GetOcState() > OC_LOADED) {
TransitionDownTo(OC_LOADED);
TransitionUpTo(OC_INPLACE);
ContainerControl f = ContainingControl;
if (f != null && f.Visible && Visible)
MakeVisibleWithShow();
}
if (olduMode != newuMode && !IsHandleCreated && !axState[disposed]) {
if (GetOcx() != null) {
RealizeStyles();
}
}
if (!newuMode) {
//SetupClass_Info(this);
}
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.OnLostFocus"]/*' />
/// <devdoc>
/// <para>Raises the <see cref='System.Windows.Forms.Control.LostFocus'/> event.</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected override void OnLostFocus(EventArgs e) {
// ASURT 93669
// Office WebControl and MS DDS control create a child window that gains
// focus in order to handle keyboard input. Since, UIDeactivate() could
// destroy that window, these controls will crash trying to process WM_CHAR.
// We now check to see if we are losing focus to a child, and if so, not call
// UIDeactivate().
//
bool uiDeactivate = (GetHandleNoCreate() != hwndFocus);
if (uiDeactivate && IsHandleCreated) {
uiDeactivate = !UnsafeNativeMethods.IsChild(new HandleRef(this, GetHandleNoCreate()), new HandleRef(null, hwndFocus));
}
base.OnLostFocus(e);
if (uiDeactivate) {
UiDeactivate();
}
}
private void OnNewSelection(Object sender, EventArgs e) {
if (IsUserMode()) return;
ISelectionService iss = GetSelectionService();
// What we care about:
// if we are uiactive and we lose selection, then we need to uideactivate ourselves...
if (iss != null) {
if (GetOcState() >= OC_UIACTIVE && !iss.GetComponentSelected(this)) {
// need to deactivate...
int hr = UiDeactivate();
if (NativeMethods.Failed(hr)) {
// not much we can do here...
Debug.Fail("Failed to UiDeactivate: " + hr.ToString(CultureInfo.InvariantCulture));
}
}
if (!iss.GetComponentSelected(this)) {
if (editMode != EDITM_NONE) {
GetParentContainer().OnExitEditMode(this);
editMode = EDITM_NONE;
}
// need to exit edit mode...
SetSelectionStyle(1);
RemoveSelectionHandler();
}
else {
// The AX Host designer will offer an extender property called "SelectionStyle"
//
PropertyDescriptor prop = TypeDescriptor.GetProperties(this)["SelectionStyle"];
if (prop != null && prop.PropertyType == typeof(int)) {
int curSelectionStyle = (int)prop.GetValue(this);
if (curSelectionStyle != this.selectionStyle) {
prop.SetValue(this, selectionStyle);
}
}
}
}
}
//DrawToBitmap doesn't work for this control, so we should hide it. We'll
//still call base so that this has a chance to work if it can.
[EditorBrowsable(EditorBrowsableState.Never)]
new public void DrawToBitmap(Bitmap bitmap, Rectangle targetBounds)
{
base.DrawToBitmap(bitmap, targetBounds);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.CreateHandle"]/*' />
/// <devdoc>
/// Creates a handle for this control. This method is called by the .NET framework, this should
/// not be called.
/// </devdoc>
protected override void CreateHandle() {
if (!IsHandleCreated) {
TransitionUpTo(OC_RUNNING);
if (!axState[fOwnWindow]) {
if (axState[fNeedOwnWindow]) {
Debug.Assert(!Visible, "if we were visible we would not be needing a fake window...");
axState[fNeedOwnWindow] = false;
axState[fFakingWindow] = true;
base.CreateHandle();
// note that we do not need to attach the handle because the work usually done in there
// will be done in Control's wndProc on WM_CREATE...
}
else {
TransitionUpTo(OC_INPLACE);
// it is possible that we were hidden while in place activating, in which case we don't
// really have a handle now because the act of hiding could have destroyed it
// so, just call ourselves again recursively, and if we dont't have a handle, we will
// just take the "axState[fNeedOwnWindow]" path above...
if (axState[fNeedOwnWindow]) {
Debug.Assert(!IsHandleCreated, "if we need a fake window, we can't have a real one");
CreateHandle();
return;
}
}
}
else {
SetState(STATE_VISIBLE, false);
base.CreateHandle();
}
GetParentContainer().ControlCreated(this);
}
}
private NativeMethods.COMRECT GetClipRect(NativeMethods.COMRECT clipRect) {
if (clipRect != null) {
FillInRect(clipRect, new Rectangle(0, 0, 32000, 32000));
}
return clipRect;
}
private static int SetupLogPixels(bool force) {
if (logPixelsX == -1 || force) {
IntPtr hDC = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef);
if (hDC == IntPtr.Zero)
return NativeMethods.E_FAIL;
logPixelsX = UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, hDC), NativeMethods.LOGPIXELSX);
logPixelsY = UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, hDC), NativeMethods.LOGPIXELSY);
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "log pixels are: "+logPixelsX.ToString(CultureInfo.InvariantCulture)+" "+logPixelsY.ToString(CultureInfo.InvariantCulture));
UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, hDC));
}
return NativeMethods.S_OK;
}
private void HiMetric2Pixel(NativeMethods.tagSIZEL sz, NativeMethods.tagSIZEL szout) {
NativeMethods._POINTL phm = new NativeMethods._POINTL();
phm.x = sz.cx;
phm.y = sz.cy;
NativeMethods.tagPOINTF pcont = new NativeMethods.tagPOINTF();
((UnsafeNativeMethods.IOleControlSite)oleSite).TransformCoords(phm, pcont, NativeMethods.ActiveX.XFORMCOORDS_SIZE | NativeMethods.ActiveX.XFORMCOORDS_HIMETRICTOCONTAINER);
szout.cx = (int)pcont.x;
szout.cy = (int)pcont.y;
}
private void Pixel2hiMetric(NativeMethods.tagSIZEL sz, NativeMethods.tagSIZEL szout) {
NativeMethods.tagPOINTF pcont = new NativeMethods.tagPOINTF();
pcont.x = (float) sz.cx;
pcont.y = (float) sz.cy;
NativeMethods._POINTL phm = new NativeMethods._POINTL();
((UnsafeNativeMethods.IOleControlSite)oleSite).TransformCoords(phm, pcont, NativeMethods.ActiveX.XFORMCOORDS_SIZE | NativeMethods.ActiveX.XFORMCOORDS_CONTAINERTOHIMETRIC);
szout.cx = phm.x;
szout.cy = phm.y;
}
private static int Pixel2Twip(int v, bool xDirection) {
SetupLogPixels(false);
int logP = xDirection ? logPixelsX : logPixelsY;
return(int) ((((double)v) / logP) * 72.0 * 20.0);
}
private static int Twip2Pixel(double v, bool xDirection) {
SetupLogPixels(false);
int logP = xDirection ? logPixelsX : logPixelsY;
return(int) (((v / 20.0) / 72.0) * logP);
}
private static int Twip2Pixel(int v, bool xDirection) {
SetupLogPixels(false);
int logP = xDirection ? logPixelsX : logPixelsY;
return(int) (((((double) v) / 20.0) / 72.0) * logP);
}
private Size SetExtent(int width, int height) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "setting extent to "+width.ToString(CultureInfo.InvariantCulture)+" "+height.ToString(CultureInfo.InvariantCulture));
NativeMethods.tagSIZEL sz = new NativeMethods.tagSIZEL();
sz.cx = width;
sz.cy = height;
bool resetExtents = !IsUserMode();
try {
Pixel2hiMetric(sz, sz);
GetOleObject().SetExtent(NativeMethods.ActiveX.DVASPECT_CONTENT, sz);
}
catch (COMException) {
resetExtents = true;
}
if (resetExtents) {
GetOleObject().GetExtent(NativeMethods.ActiveX.DVASPECT_CONTENT, sz);
try {
GetOleObject().SetExtent(NativeMethods.ActiveX.DVASPECT_CONTENT, sz);
}
catch (COMException e) {
Debug.Fail(e.ToString());
}
}
return GetExtent();
}
private Size GetExtent() {
NativeMethods.tagSIZEL sz = new NativeMethods.tagSIZEL();
GetOleObject().GetExtent(NativeMethods.ActiveX.DVASPECT_CONTENT, sz);
HiMetric2Pixel(sz, sz);
return new Size(sz.cx, sz.cy);
}
/// <include file='doc\Control.uex' path='docs/doc[@for="AxHost.GetScaledBounds"]/*' />
/// <devdoc>
/// ActiveX controls scale themselves, so GetScaledBounds simply returns their
/// original unscaled bounds.
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected override Rectangle GetScaledBounds(Rectangle bounds, SizeF factor, BoundsSpecified specified) {
return bounds;
}
private void SetObjectRects(Rectangle bounds) {
if (GetOcState() < OC_INPLACE) return;
GetInPlaceObject().SetObjectRects(FillInRect(new NativeMethods.COMRECT(), bounds), GetClipRect(new NativeMethods.COMRECT()));
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.SetBoundsCore"]/*' />
/// <devdoc>
/// Performs the work of setting the bounds of this control.
/// User code should usually not call this function.
/// </devdoc>
protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
// We have already been in this Code so please avoid re-entering this CODE PATH or else the
// IOleObject will "give a Catastrophic error" in SetObjectRects( ).
// Please refer : VsWhidbey 341212.
if (GetAxState(AxHost.handlePosRectChanged))
return;
axState[handlePosRectChanged] = true;
// Provide control with an opportunity to apply self imposed constraints on its size.
Size adjustedSize = ApplySizeConstraints(width, height);
width = adjustedSize.Width;
height = adjustedSize.Height;
try {
if (axState[fFakingWindow]) {
base.SetBoundsCore(x, y, width, height, specified);
return;
}
Rectangle oldBounds = Bounds;
if (oldBounds.X == x && oldBounds.Y == y && oldBounds.Width == width &&
oldBounds.Height == height) {
return;
}
if (!IsHandleCreated) {
UpdateBounds(x, y, width, height);
return;
}
if (GetOcState() > OC_RUNNING) {
CheckSubclassing();
if (width != oldBounds.Width || height != oldBounds.Height) {
Size p = SetExtent(width, height);
width = p.Width;
height = p.Height;
}
}
if (axState[manualUpdate]) {
SetObjectRects(new Rectangle(x, y, width, height));
CheckSubclassing();
UpdateBounds();
}
else {
SetObjectRects(new Rectangle(x, y, width, height));
base.SetBoundsCore(x, y, width, height, specified);
Invalidate();
}
}
finally {
axState[handlePosRectChanged] = false;
}
}
private bool CheckSubclassing() {
if (!IsHandleCreated || wndprocAddr == IntPtr.Zero) return true;
IntPtr handle = Handle;
IntPtr currentWndproc = UnsafeNativeMethods.GetWindowLong(new HandleRef(this, handle), NativeMethods.GWL_WNDPROC);
if (currentWndproc == wndprocAddr) return true;
if (unchecked( (int) (long)SendMessage(REGMSG_MSG, 0, 0)) == REGMSG_RETVAL) {
wndprocAddr = currentWndproc;
return true;
}
// yikes, we were resubclassed...
Debug.WriteLineIf(AxHostSwitch.TraceVerbose, "The horrible control subclassed itself w/o calling the old wndproc...");
// we need to resubclass outselves now...
Debug.Assert(!OwnWindow(), "why are we here if we own our window?");
this.WindowReleaseHandle();
UnsafeNativeMethods.SetWindowLong(new HandleRef(this, handle), NativeMethods.GWL_WNDPROC, new HandleRef(this, currentWndproc));
this.WindowAssignHandle(handle, axState[assignUniqueID]);
InformOfNewHandle();
axState[manualUpdate] = true;
return false;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.DestroyHandle"]/*' />
/// <devdoc>
/// Destroys the handle associated with this control.
/// User code should in general not call this function.
/// </devdoc>
[SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
// security review: this is a breaking change, but should it be fixed?
protected override void DestroyHandle() {
if (axState[fOwnWindow]) {
base.DestroyHandle();
}
else {
if (IsHandleCreated) {
TransitionDownTo(OC_RUNNING);
}
}
}
#if false
// FxCop: Currently not used
private void TransitionTo(int state) {
if (state > GetOcState()) {
TransitionUpTo(state);
}
else if (state < GetOcState()) {
TransitionDownTo(state);
}
}
#endif
private void TransitionDownTo(int state) {
if (axState[inTransition]) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Recursively entering TransitionDownTo...");
return;
}
try {
axState[inTransition] = true;
while (state < GetOcState()) {
switch (GetOcState()) {
case OC_OPEN:
Debug.Fail("how did we ever get into the open state?");
SetOcState(OC_UIACTIVE);
break;
case OC_UIACTIVE:
int hr = UiDeactivate();
Debug.Assert(NativeMethods.Succeeded(hr), "Failed in UiDeactivate: " + hr.ToString(CultureInfo.InvariantCulture));
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose && GetOcState() == OC_INPLACE, "failed transition");
SetOcState(OC_INPLACE);
break;
case OC_INPLACE:
if (axState[fFakingWindow]) {
DestroyFakeWindow();
SetOcState(OC_RUNNING);
}
else {
InPlaceDeactivate();
}
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose && GetOcState() == OC_RUNNING, "failed transition");
SetOcState(OC_RUNNING);
break;
case OC_RUNNING:
StopEvents();
DisposeAxControl();
Debug.Assert(GetOcState() == OC_LOADED," failed transition");
SetOcState(OC_LOADED);
break;
case OC_LOADED:
ReleaseAxControl();
Debug.Assert(GetOcState() == OC_PASSIVE," failed transition");
SetOcState(OC_PASSIVE);
break;
default:
Debug.Fail("bad state");
SetOcState(GetOcState() - 1);
break;
}
}
}
finally {
axState[inTransition] = false;
}
}
private void TransitionUpTo(int state) {
if (axState[inTransition]) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Recursively entering TransitionUpTo...");
return;
}
try {
axState[inTransition] = true;
while (state > GetOcState()) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Transitioning up from: " + GetOcState().ToString(CultureInfo.InvariantCulture) + " to: " + state.ToString(CultureInfo.InvariantCulture));
switch (GetOcState()) {
case OC_PASSIVE:
axState[disposed] = false;
GetOcxCreate();
Debug.Assert(GetOcState() == OC_LOADED, " failed transition");
SetOcState(OC_LOADED);
break;
case OC_LOADED:
ActivateAxControl();
Debug.Assert(GetOcState() == OC_RUNNING, " failed transition");
SetOcState(OC_RUNNING);
if (IsUserMode()) {
// start the events flowing!
//createSink();
StartEvents();
}
break;
case OC_RUNNING:
axState[ownDisposing] = false;
Debug.Assert(!axState[fOwnWindow], "If we are invis at runtime, we should never be going beynd OC_RUNNING");
if (!axState[fOwnWindow]) {
InPlaceActivate();
if (!Visible && ContainingControl != null && ContainingControl.Visible) {
HideAxControl();
}
else {
// if we do this in both codepaths, then we will force handle creation of the fake window
// even if we don't need it...
// This optimization will break, however, if:
// a) the hWnd goes away on a OLEIVERB_HIDE and
// b) this is a simple frame control
// However, if you satisfy both of these conditions then you must be REALLY
// brain dead and you don't deserve to work anyway...
CreateControl(true);
// if our default size is wrong for the control, let's resize ourselves...
// Note: some controls haven't updated their extents at this time
// (even though they got it from the DoVerb call and
// also from GetWindowContext) so we don't poke in a new value.
// The reason to do this at design time is that that's the only way we
// can find out if the control has a default which we have to obey.
if (!IsUserMode() && !axState[ocxStateSet]) {
Size p = GetExtent();
Rectangle b = Bounds;
if ((b.Size.Equals(DefaultSize)) && (!b.Size.Equals(p))) {
b.Width = p.Width;
b.Height = p.Height;
Bounds = b;
}
}
}
}
//Debug.Assert(GetOcState() == OC_INPLACE, " failed transition");
if (GetOcState() < OC_INPLACE) {
SetOcState(OC_INPLACE);
}
OnInPlaceActive();
break;
case OC_INPLACE:
DoVerb(OLEIVERB_SHOW);
Debug.Assert(GetOcState() == OC_UIACTIVE, " failed transition");
SetOcState(OC_UIACTIVE);
break;
default:
Debug.Fail("bad state");
SetOcState(GetOcState() + 1);
break;
}
}
}
finally {
axState[inTransition] = false;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.OnInPlaceActive"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
/// <internalonly/>
protected virtual void OnInPlaceActive() {
}
private void InPlaceActivate() {
try {
DoVerb(OLEIVERB_INPLACEACTIVATE);
}
catch (Exception t) {
Debug.Fail(t.ToString());
throw new TargetInvocationException(SR.GetString(SR.AXNohWnd,GetType().Name), t);
}
EnsureWindowPresent();
}
private void InPlaceDeactivate() {
axState[ownDisposing] = true;
ContainerControl f = ContainingControl;
if (f != null) {
if (f.ActiveControl == this) {
f.ActiveControl = null;
}
}
try {
GetInPlaceObject().InPlaceDeactivate();
}
catch(Exception e) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Exception calling InPlaceDeactivate: "+ e.ToString());
}
}
private void UiActivate() {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "calling uiActivate for "+this.ToString());
Debug.Assert(GetOcState() >= OC_INPLACE, "we have to be in place in order to ui activate...");
Debug.Assert(CanUIActivate, "we have to be able to uiactivate");
if (CanUIActivate) {
DoVerb(OLEIVERB_UIACTIVATE);
}
}
private void DestroyFakeWindow() {
Debug.Assert(axState[fFakingWindow], "have to be faking it in order to destroy it...");
// ASURT 70740: The problem seems to be that when we try to destroy the fake window,
// we recurse in and transition the control down to OC_RUNNING. This causes the control's
// new window to get destroyed also, and the control never shows up.
// We now prevent this by changing our state about the fakeWindow _before_ we actually
// destroy the window.
//
axState[fFakingWindow] = false;
base.DestroyHandle();
}
private void EnsureWindowPresent() {
// if the ctl didn't call showobject, we need to do it for it...
if (!IsHandleCreated) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Naughty control didn't call showObject...");
try {
((UnsafeNativeMethods.IOleClientSite)oleSite).ShowObject();
}
catch {
// The exception, if any was already dumped in ShowObject
}
}
if (IsHandleCreated) return;
if (ParentInternal != null) { // ==> we are in a valid state
Debug.Fail("extremely naughty ctl is refusing to give us an hWnd... giving up...");
throw new NotSupportedException(SR.GetString(SR.AXNohWnd,GetType().Name));
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.SetVisibleCore"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
protected override void SetVisibleCore(bool value) {
if (GetState(STATE_VISIBLE) != value) {
bool oldVisible = Visible;
if ((IsHandleCreated || value) && ParentInternal != null && ParentInternal.Created) {
if (!axState[fOwnWindow]) {
TransitionUpTo(OC_RUNNING);
if (value) {
if (axState[fFakingWindow]) {
// first we need to destroy the fake window...
DestroyFakeWindow();
}
// We want to avoid using SHOW since that may uiactivate us, and we don't
// want that...
if (!IsHandleCreated) {
// So, if we don't have a handle, we just try to create it and hope that this will make
// us appear...
try {
SetExtent(Width, Height);
InPlaceActivate();
CreateControl(true);
}
catch {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Could not make ctl visible by using INPLACE. Will try SHOW");
MakeVisibleWithShow();
}
}
else {
// if, otoh, we had a handle to begin with, we need to use show since INPLACE is just
// a noop...
MakeVisibleWithShow();
}
}
else {
Debug.Assert(!axState[fFakingWindow], "if we were visible, we could not have had a fake window...");
HideAxControl();
}
}
}
if (!value) {
axState[fNeedOwnWindow] = false;
}
if (!axState[fOwnWindow]) {
SetState(STATE_VISIBLE, value);
if (Visible != oldVisible)
OnVisibleChanged(EventArgs.Empty);
}
}
}
private void MakeVisibleWithShow() {
ContainerControl f = ContainingControl;
Control ctl = f == null ? null : f.ActiveControl;
try {
DoVerb(OLEIVERB_SHOW);
}
catch (Exception t) {
Debug.Fail(t.ToString());
throw new TargetInvocationException(SR.GetString(SR.AXNohWnd,GetType().Name), t);
}
EnsureWindowPresent();
CreateControl(true);
if (f != null && f.ActiveControl != ctl) {
f.ActiveControl = ctl;
}
}
private void HideAxControl() {
Debug.Assert(!axState[fOwnWindow], "can't own our window when hiding");
Debug.Assert(IsHandleCreated, "gotta have a window to hide");
Debug.Assert(GetOcState() >= OC_INPLACE, "have to be in place in order to hide.");
DoVerb(OLEIVERB_HIDE);
if (GetOcState() < OC_INPLACE) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Naughty control inplace deactivated on a hide verb...");
Debug.Assert(!IsHandleCreated, "if we are inplace deactivated we should not have a window.");
// all we do here is set a flag saying that we need the window to be created if
// create handle is ever called...
axState[fNeedOwnWindow] = true;
// also, set the state to our "pretend oc_inplace state"
//
SetOcState(OC_INPLACE);
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.IsInputChar"]/*' />
/// <devdoc>
/// Determines if charCode is an input character that the control
/// wants. This method is called during window message pre-processing to
/// determine whether the given input character should be pre-processed or
/// sent directly to the control. If isInputChar returns true, the
/// given character is sent directly to the control. If isInputChar
/// returns false, the character is pre-processed and only sent to the
/// control if it is not consumed by the pre-processing phase. The
/// pre-processing of a character includes checking whether the character
/// is a mnemonic of another control.
/// </devdoc>
[UIPermission(SecurityAction.InheritanceDemand, Window=UIPermissionWindow.AllWindows)]
protected override bool IsInputChar(char charCode) {
return true;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ProcessDialogKey"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[SuppressMessage("Microsoft.Security", "CA2114:MethodSecurityShouldBeASupersetOfType")]
[UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
protected override bool ProcessDialogKey(Keys keyData)
{
return ignoreDialogKeys ? false : base.ProcessDialogKey(keyData);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.PreProcessMessage"]/*' />
/// <devdoc>
/// This method is called by the application's message loop to pre-process
/// input messages before they are dispatched. Possible values for the
/// msg.message field are WM_KEYDOWN, WM_SYSKEYDOWN, WM_CHAR, and WM_SYSCHAR.
/// If this method processes the message it must return true, in which case
/// the message loop will not dispatch the message.
/// This method should not be called directly by the user.
///
/// The keyboard processing of input keys to AxHost controls go in 3 steps inside AxHost.PreProcessMessage()
///
/// (1) Call the OCX's TranslateAccelarator. This may or may not call back into us using IOleControlSite::TranslateAccelarator()
///
/// (2) If the control completely processed this without calling us back:
/// -- If this returns S_OK, then it means that the control already processed this message and we return true,
/// forcing us to not do any more processing or dispatch the message.
/// -- If this returns S_FALSE, then it means that the control wants us to dispatch the message without doing any processing on our side.
///
/// (3) If the control completely processed this by calling us back:
/// -- If this returns S_OK, then it means that the control processed this message and we return true,
/// forcing us to not do any more processing or dispatch the message.
/// -- If this returns S_FALSE, then it means that the control did not process this message,
/// but we did, and so we should route it through our PreProcessMessage().
/// </devdoc>
public override bool PreProcessMessage(ref Message msg) {
Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "AxHost.PreProcessMessage " + msg.ToString());
if (IsUserMode()) {
if (axState[siteProcessedInputKey]) {
// In this case, the control called the us back through the IControlSite
// and giving us a chance to see if we want to process it. We in turn
// call the base implementation which normally would call the control's
// IsInputKey() or IsInputChar(). So, we short-circuit those to return false
// and only return true, if the container-chain wanted to process the keystroke
// (e.g. tab, accelarators etc.)
//
return base.PreProcessMessage(ref msg);
}
NativeMethods.MSG win32Message = new NativeMethods.MSG();
win32Message.message = msg.Msg;
win32Message.wParam = msg.WParam;
win32Message.lParam = msg.LParam;
win32Message.hwnd = msg.HWnd;
axState[siteProcessedInputKey] = false;
try {
UnsafeNativeMethods.IOleInPlaceActiveObject activeObj = GetInPlaceActiveObject();
if (activeObj != null)
{
int hr = activeObj.TranslateAccelerator(ref win32Message);
msg.Msg = win32Message.message;
msg.WParam = win32Message.wParam;
msg.LParam = win32Message.lParam;
msg.HWnd = win32Message.hwnd;
if (hr == NativeMethods.S_OK) {
Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "\t Message translated by control to " + msg);
return true;
}
else if (hr == NativeMethods.S_FALSE) {
bool ret = false;
ignoreDialogKeys = true;
try {
ret = base.PreProcessMessage(ref msg);
}
finally {
ignoreDialogKeys = false;
}
return ret;
}
else if (axState[siteProcessedInputKey]) {
Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "\t Message processed by site. Calling base.PreProcessMessage() " + msg);
return base.PreProcessMessage (ref msg);
}
else {
Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "\t Message not processed by site. Returning false. " + msg);
return false;
}
}
}
finally {
axState[siteProcessedInputKey] = false;
}
}
return false;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ProcessMnemonic"]/*' />
/// <devdoc>
/// Process a mnemonic character.
/// This is done by manufacturing a WM_SYSKEYDOWN message and passing it
/// to the ActiveX control.
/// </devdoc>
[SuppressMessage("Microsoft.Security", "CA2114:MethodSecurityShouldBeASupersetOfType")]
[UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
protected internal override bool ProcessMnemonic(char charCode) {
Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "In AxHost.ProcessMnemonic: " + (int)charCode);
if (CanSelect) {
try {
NativeMethods.tagCONTROLINFO ctlInfo = new NativeMethods.tagCONTROLINFO();
int hr = GetOleControl().GetControlInfo(ctlInfo);
if (NativeMethods.Failed(hr)) {
return false;
}
NativeMethods.MSG msg = new NativeMethods.MSG();
// Sadly, we don't have a message so we must fake one ourselves...
// A bit of ugliness here (a bit? more like a bucket...)
// The message we are faking is a WM_SYSKEYDOWN w/ the right alt key setting...
msg.hwnd = (ContainingControl == null) ? IntPtr.Zero : ContainingControl.Handle;
msg.message = NativeMethods.WM_SYSKEYDOWN;
msg.wParam = (IntPtr) Char.ToUpper(charCode, CultureInfo.CurrentCulture);
msg.lParam = (IntPtr) 0x20180001;
msg.time = SafeNativeMethods.GetTickCount();
NativeMethods.POINT p = new NativeMethods.POINT();
UnsafeNativeMethods.GetCursorPos(p);
msg.pt_x = p.x;
msg.pt_y = p.y;
if (SafeNativeMethods.IsAccelerator(new HandleRef(ctlInfo, ctlInfo.hAccel), ctlInfo.cAccel, ref msg, null)) {
GetOleControl().OnMnemonic(ref msg);
Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "\t Processed mnemonic " + msg);
Focus();
return true;
}
}
catch (Exception t) {
Debug.Fail("error in processMnemonic");
Debug.Fail(t.ToString());
return false;
}
}
return false;
}
// misc methods:
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.SetAboutBoxDelegate"]/*' />
/// <devdoc>
/// Sets the delegate which will be called when the user selects the "About..."
/// entry on the context menu.
/// </devdoc>
protected void SetAboutBoxDelegate(AboutBoxDelegate d) {
aboutBoxDelegate += d;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.OcxState"]/*' />
/// <devdoc>
/// Sets the persisted state of the control.
/// This should either be null, obtained from getOcxState, or
/// read from a resource. The value of this property will
/// be used after the control is created but before it is
/// shown.
/// Computes the persisted state of the underlying ActiveX control and
/// returns it in the encapsulated State object.
/// If the control has been modified since it was last saved to a
/// persisted state, it will be asked to save itself.
/// </devdoc>
[
DefaultValue(null),
RefreshProperties(RefreshProperties.All),
Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced)
]
public State OcxState {
get {
if (IsDirty() || ocxState == null) {
Debug.Assert(!axState[disposed], "we chould not be asking for the object when we are axState[disposed]...");
ocxState = CreateNewOcxState(ocxState);
}
return ocxState;
}
set {
axState[ocxStateSet] = true;
if (value == null) return;
if (storageType != STG_UNKNOWN && storageType != value.type) {
Debug.Fail("Trying to reload with a OcxState that is of a different type.");
throw new InvalidOperationException(SR.GetString(SR.AXOcxStateLoaded));
}
if (this.ocxState == value)
return;
this.ocxState = value;
if (this.ocxState != null) {
this.axState[manualUpdate] = ocxState._GetManualUpdate();
this.licenseKey = ocxState._GetLicenseKey();
}
else {
this.axState[manualUpdate] = false;
this.licenseKey = null;
}
if (this.ocxState != null && GetOcState() >= OC_RUNNING) {
DepersistControl();
}
}
}
private State CreateNewOcxState(State oldOcxState) {
NoComponentChangeEvents++;
try {
if (GetOcState() < OC_RUNNING) {
return null;
}
try {
PropertyBagStream propBag = null;
if (iPersistPropBag != null) {
propBag = new PropertyBagStream();
iPersistPropBag.Save(propBag, true, true);
}
MemoryStream ms = null;
switch (storageType) {
case STG_STREAM:
case STG_STREAMINIT:
ms = new MemoryStream();
if (storageType == STG_STREAM) {
iPersistStream.Save(new UnsafeNativeMethods.ComStreamFromDataStream(ms), true);
}
else {
iPersistStreamInit.Save(new UnsafeNativeMethods.ComStreamFromDataStream(ms), true);
}
break;
case STG_STORAGE:
Debug.Assert(oldOcxState != null, "we got to have an old state which holds out scribble storage...");
if (oldOcxState != null) return oldOcxState.RefreshStorage(iPersistStorage);
return null;
default:
Debug.Fail("unknown storage type.");
return null;
}
if (ms != null) {
return new State(ms, storageType, this, propBag);
}
else if (propBag != null) {
return new State(propBag);
}
}
catch (Exception e) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Could not create new OCX State: " + e.ToString());
}
}
finally {
NoComponentChangeEvents--;
}
return null;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ContainerControl"]/*' />
/// <devdoc>
/// Returns this control's logicaly containing form.
/// At design time this is always the form being designed.
/// At runtime it is either the form set with setContainingForm or,
/// by default, the parent form.
/// Sets the form which is the logical container of this control.
/// By default, the parent form performs that function. It is
/// however possible for another form higher in the parent chain
/// to serve in that role. The logical container of this
/// control determines the set of logical sibling control.
/// In general this property exists only to enable some speficic
/// behaviours of ActiveX controls and should in general not be set
/// by the user.
/// </devdoc>
[
Browsable(false),
EditorBrowsable(EditorBrowsableState.Advanced),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public ContainerControl ContainingControl {
get {
Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "GetParent Demanded");
IntSecurity.GetParent.Demand();
if (containingControl == null) {
containingControl = FindContainerControlInternal();
}
return containingControl;
}
set {
containingControl = value;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ShouldSerializeText"]/*' />
/// <devdoc>
/// <para>Determines if the Text property needs to be persisted.</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Never)]
internal override bool ShouldSerializeText() {
bool ret = false;
try {
ret = (Text.Length != 0);
}
catch (COMException) {
}
return ret;
}
/// <devdoc>
/// Determines whether to persist the ContainingControl property.
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Never)]
private bool ShouldSerializeContainingControl() {
return ContainingControl != ParentInternal;
}
private ContainerControl FindContainerControlInternal() {
if (Site != null) {
IDesignerHost host = (IDesignerHost)Site.GetService(typeof(IDesignerHost));
if (host != null) {
ContainerControl rootControl = host.RootComponent as ContainerControl;
if (rootControl != null)
{
return rootControl;
}
}
}
ContainerControl cc = null;
Control control = this;
while (control != null) {
ContainerControl tempCC = control as ContainerControl;
if (tempCC != null)
{
cc = tempCC;
break;
}
control = control.ParentInternal;
}
return cc;
}
private bool IsDirty() {
if (GetOcState() < OC_RUNNING) return false;
Debug.Assert(storageType != STG_UNKNOWN, "if we are loaded, out storage type must be set!");
if (axState[valueChanged]) {
axState[valueChanged] = false;
return true;
}
#if DEBUG
if (AxAlwaysSaveSwitch.Enabled) return true;
#endif
int hr = NativeMethods.E_FAIL;
switch (storageType) {
case STG_STREAM:
hr = iPersistStream.IsDirty();
break;
case STG_STREAMINIT:
hr = iPersistStreamInit.IsDirty();
break;
case STG_STORAGE:
hr = iPersistStorage.IsDirty();
break;
default:
Debug.Fail("unknown storage type");
return true;
}
if (hr == NativeMethods.S_FALSE) {
// NOTE: This was a note from the old AxHost codebase. The problem
// with doing this is that the some controls that do not run in
// unlicensed mode (e.g. ProtoView ScheduleX pvtaskpad.ocx) will
// always return S_FALSE to disallow design-time support.
// Sadly, some controls lie and never say that they are dirty...
// SO, we don't believe them unless they told us that they were
// dirty at least once...
return false;
}
else if (NativeMethods.Failed(hr)) {
return true;
}
return true;
}
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
internal bool IsUserMode() {
ISite site = Site;
return site == null || !site.DesignMode;
}
private Object GetAmbientProperty(int dispid) {
Control richParent = ParentInternal;
switch (dispid) {
case NativeMethods.ActiveX.DISPID_AMBIENT_USERMODE:
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "asked for usermode");
return IsUserMode();
case NativeMethods.ActiveX.DISPID_AMBIENT_AUTOCLIP:
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "asked for autoclip");
return true;
case NativeMethods.ActiveX.DISPID_AMBIENT_MESSAGEREFLECT:
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "asked for message reflect");
return true;
case NativeMethods.ActiveX.DISPID_AMBIENT_UIDEAD:
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "asked for uidead");
return false;
case NativeMethods.ActiveX.DISPID_AMBIENT_DISPLAYASDEFAULT:
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "asked for displayasdefault");
return false;
case NativeMethods.ActiveX.DISPID_AMBIENT_FONT:
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "asked for font");
if (richParent != null) {
return GetIFontFromFont(richParent.Font);
}
return null;
case NativeMethods.ActiveX.DISPID_AMBIENT_SHOWGRABHANDLES:
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "asked for showGrabHandles");
return false;
case NativeMethods.ActiveX.DISPID_AMBIENT_SHOWHATCHING:
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "asked for showHatching");
return false;
case NativeMethods.ActiveX.DISPID_AMBIENT_BACKCOLOR:
if (richParent != null) {
return GetOleColorFromColor(richParent.BackColor);
}
return null;
case NativeMethods.ActiveX.DISPID_AMBIENT_FORECOLOR:
if (richParent != null) {
return GetOleColorFromColor(richParent.ForeColor);
}
return null;
case NativeMethods.ActiveX.DISPID_AMBIENT_DISPLAYNAME:
string rval = GetParentContainer().GetNameForControl(this);
if (rval == null) rval = "";
return rval;
case NativeMethods.ActiveX.DISPID_AMBIENT_LOCALEID:
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "asked for localeid");
return Thread.CurrentThread.CurrentCulture.LCID;
case NativeMethods.ActiveX.DISPID_AMBIENT_RIGHTTOLEFT:
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "asked for right to left");
Control ctl = this;
while (ctl != null) {
if (ctl.RightToLeft == System.Windows.Forms.RightToLeft.No)
return false;
if (ctl.RightToLeft == System.Windows.Forms.RightToLeft.Yes)
return true;
if (ctl.RightToLeft == System.Windows.Forms.RightToLeft.Inherit)
ctl = ctl.Parent;
}
return null;
default:
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "unsupported ambient "+dispid.ToString(CultureInfo.InvariantCulture));
return null;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.DoVerb"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public void DoVerb(int verb) {
Control parent = ParentInternal;
GetOleObject().DoVerb(verb, IntPtr.Zero, oleSite, -1, parent != null ? parent.Handle : IntPtr.Zero, FillInRect(new NativeMethods.COMRECT(), Bounds));
}
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
private bool AwaitingDefreezing() {
return freezeCount > 0;
}
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
private void Freeze(bool v) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "freezing "+v.ToString());
if (v) {
try {
GetOleControl().FreezeEvents(-1);
}
catch (COMException t) {
Debug.Fail(t.ToString());
}
freezeCount ++;
}
else {
try {
GetOleControl().FreezeEvents(0);
}
catch (COMException t) {
Debug.Fail(t.ToString());
}
freezeCount --;
}
Debug.Assert(freezeCount >=0, "invalid freeze count!");
}
private int UiDeactivate() {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "calling uiDeactivate for "+this.ToString());
bool ownDispose = this.axState[ownDisposing];
this.axState[ownDisposing] = true;
int hr = 0;
try {
hr = GetInPlaceObject().UIDeactivate();
}
finally {
this.axState[ownDisposing] = ownDispose;
}
return hr;
}
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
private int GetOcState() {
return ocState;
}
private void SetOcState(int nv) {
ocState = nv;
}
private string GetLicenseKey() {
return GetLicenseKey(this.clsid);
}
private string GetLicenseKey(Guid clsid) {
if (licenseKey != null || !axState[needLicenseKey]) {
return licenseKey;
}
try {
UnsafeNativeMethods.IClassFactory2 icf2 = UnsafeNativeMethods.CoGetClassObject(ref clsid, INPROC_SERVER, 0, ref icf2_Guid);
NativeMethods.tagLICINFO licInfo = new NativeMethods.tagLICINFO();
icf2.GetLicInfo(licInfo);
if (licInfo.fRuntimeAvailable != 0) {
string[] rval = new string[1];
icf2.RequestLicKey(0, rval);
licenseKey = rval[0];
return licenseKey;
}
}
catch (COMException e) {
if (e.ErrorCode == E_NOINTERFACE.ErrorCode) return null;
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Failed to get the license key: " + e.ToString());
axState[needLicenseKey] = false;
}
catch (Exception t) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Failed to get the license key: " + t.ToString());
axState[needLicenseKey] = false;
}
return null;
}
private void CreateWithoutLicense(Guid clsid) {
object ret = null;
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Creating object without license: " + clsid.ToString());
ret = UnsafeNativeMethods.CoCreateInstance(ref clsid, null, INPROC_SERVER, ref NativeMethods.ActiveX.IID_IUnknown);
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "\t" + (ret != null).ToString());
instance = ret;
}
private void CreateWithLicense(string license, Guid clsid) {
if (license != null) {
try {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Creating object with license: " + clsid.ToString());
UnsafeNativeMethods.IClassFactory2 icf2 = UnsafeNativeMethods.CoGetClassObject(ref clsid, INPROC_SERVER, 0, ref icf2_Guid);
if (icf2 != null) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "\tClassFactory" + (icf2 != null).ToString());
icf2.CreateInstanceLic(null, null, ref NativeMethods.ActiveX.IID_IUnknown, license, out instance);
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "\t" + (instance != null).ToString());
}
}
catch (Exception t) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Failed to create with license: " + t.ToString());
}
}
if (instance == null) {
CreateWithoutLicense(clsid);
}
}
private void CreateInstance() {
Debug.Assert(instance == null, "instance must be null");
//Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "before created "+Windows.GetCurrentThreadId());
//Debug.WriteStackTraceIf("AxHTrace");
//checkThreadingModel();
try {
instance = CreateInstanceCore(this.clsid);
Debug.Assert(instance != null, "w/o an exception being thrown we must have an object...");
}
catch (ExternalException e) {
if (e.ErrorCode == unchecked((int)0x80040112)) { // CLASS_E_NOTLICENSED
throw new LicenseException(GetType(), this, SR.GetString(SR.AXNoLicenseToUse));
}
throw;
}
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "created");
SetOcState(OC_LOADED);
}
/// <devdoc>
/// Called to create the ActiveX control. Override this member to perform your own creation logic
/// or call base to do the default creation logic.
/// </devdoc>
protected virtual object CreateInstanceCore(Guid clsid) {
if (IsUserMode()) {
CreateWithLicense(licenseKey, clsid);
}
else {
CreateWithoutLicense(clsid);
}
return instance;
}
private CategoryAttribute GetCategoryForDispid(int dispid) {
NativeMethods.ICategorizeProperties icp = GetCategorizeProperties();
if (icp == null) return null;
CategoryAttribute rval = null;
int propcat = 0;
try {
icp.MapPropertyToCategory(dispid, ref propcat);
if (propcat != 0) {
int cat = -propcat;
if (cat > 0 && cat < categoryNames.Length && categoryNames[cat] != null) {
return categoryNames[cat];
}
cat = - cat;
Int32 key = cat;
if (objectDefinedCategoryNames != null) {
rval = (CategoryAttribute) objectDefinedCategoryNames[key];
if (rval != null) return rval;
}
string name = null;
int hr = icp.GetCategoryName(cat, CultureInfo.CurrentCulture.LCID, out name);
if (hr == NativeMethods.S_OK && name != null) {
rval = new CategoryAttribute(name);
if (objectDefinedCategoryNames == null) {
objectDefinedCategoryNames = new Hashtable();
}
objectDefinedCategoryNames.Add(key, rval);
return rval;
}
}
}
catch (Exception t) {
Debug.Fail(t.ToString());
}
return null;
}
private void SetSelectionStyle(int selectionStyle) {
if (!this.IsUserMode()) {
// selectionStyle can be 0 (not selected), 1 (selected) or 2 (active)
Debug.Assert(selectionStyle >= 0 && selectionStyle <= 2, "Invalid selection style");
ISelectionService iss = GetSelectionService();
this.selectionStyle = selectionStyle;
if (iss != null && iss.GetComponentSelected(this)) {
// The AX Host designer will offer an extender property called "SelectionStyle"
//
PropertyDescriptor prop = TypeDescriptor.GetProperties(this)["SelectionStyle"];
if (prop != null && prop.PropertyType == typeof(int)) {
prop.SetValue(this, selectionStyle);
}
}
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.InvokeEditMode"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public void InvokeEditMode() {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "invoking EditMode for "+this.ToString());
Debug.Assert((flags & AxFlags.PreventEditMode) == 0, "edit mode should have been disabled");
if (editMode != EDITM_NONE) return;
AddSelectionHandler();
editMode = EDITM_HOST;
SetSelectionStyle(2);
IntPtr hwndFocus = UnsafeNativeMethods.GetFocus();
try {
UiActivate();
}
catch (Exception t) {
Debug.Fail(t.ToString());
}
// It so happens that some controls don't get focus in this case, so
// we have got to force it onto them...
// int hwndFocusNow = NativeMethods.GetFocus();
// Windows.SetFocus(getHandle());
// while (hwndFocusNow != getHandle()) {
// if (hwndFocusNow == 0) {
// break;
// }
// hwndFocusNow = Windows.GetParent(hwndFocusNow);
// }
}
//
// ICustomTypeDescriptor implementation.
//
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetAttributes"]/*' />
/// <internalonly/>
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
AttributeCollection ICustomTypeDescriptor.GetAttributes() {
if (!axState[editorRefresh] && HasPropertyPages()) {
axState[editorRefresh] = true;
TypeDescriptor.Refresh(this.GetType());
}
return TypeDescriptor.GetAttributes(this, true);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetClassName"]/*' />
/// <internalonly/>
/// <devdoc>
/// Retrieves the class name for this object. If null is returned,
/// the type name is used.
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
string ICustomTypeDescriptor.GetClassName() {
return null;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetComponentName"]/*' />
/// <internalonly/>
/// <devdoc>
/// Retrieves the name for this object. If null is returned,
/// the default is used.
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
string ICustomTypeDescriptor.GetComponentName() {
return null;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetConverter"]/*' />
/// <internalonly/>
/// <devdoc>
/// Retrieves the type converter for this object.
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
TypeConverter ICustomTypeDescriptor.GetConverter() {
return null;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetDefaultEvent"]/*' />
/// <internalonly/>
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() {
return TypeDescriptor.GetDefaultEvent(this, true);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetDefaultProperty"]/*' />
/// <internalonly/>
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() {
return TypeDescriptor.GetDefaultProperty(this, true);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetEditor"]/*' />
/// <internalonly/>
/// <devdoc>
/// Retrieves the an editor for this object.
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
Object ICustomTypeDescriptor.GetEditor(Type editorBaseType) {
if (editorBaseType != typeof(ComponentEditor))
return null;
if (editor != null)
return editor;
if (editor == null && HasPropertyPages())
editor = new AxComponentEditor();
return editor;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetEvents"]/*' />
/// <internalonly/>
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
EventDescriptorCollection ICustomTypeDescriptor.GetEvents() {
return TypeDescriptor.GetEvents(this, true);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ICustomTypeDescriptor.GetEvents(Attribute"]/*' />
/// <internalonly/>
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) {
return TypeDescriptor.GetEvents(this, attributes, true);
}
private void OnIdle(object sender, EventArgs e) {
if (axState[refreshProperties]) {
TypeDescriptor.Refresh(this.GetType());
}
}
private bool RefreshAllProperties {
get {
return axState[refreshProperties];
}
set {
axState[refreshProperties] = value;
if (value && !axState[listeningToIdle]) {
Application.Idle += new EventHandler(this.OnIdle);
axState[listeningToIdle] = true;
}
else if (!value && axState[listeningToIdle]) {
Application.Idle -= new EventHandler(this.OnIdle);
axState[listeningToIdle] = false;
}
}
}
private PropertyDescriptorCollection FillProperties(Attribute[] attributes) {
if (RefreshAllProperties) {
RefreshAllProperties = false;
propsStash = null;
attribsStash = null;
}
else if (propsStash != null) {
if (attributes == null && attribsStash == null) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Returning stashed values for : " + "<null>");
return propsStash;
}
else if (attributes != null && attribsStash != null && attributes.Length == attribsStash.Length) {
bool attribsEqual = true;
int i = 0;
foreach(Attribute attrib in attributes) {
if (!attrib.Equals(attribsStash[i++])) {
attribsEqual = false;
break;
}
}
if (attribsEqual) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Returning stashed values for : " + attributes.Length);
return propsStash;
}
}
}
ArrayList retProps = new ArrayList();
if (properties == null)
properties = new Hashtable();
if (propertyInfos == null) {
propertyInfos = new Hashtable();
PropertyInfo[] propInfos = this.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
foreach(PropertyInfo propInfo in propInfos)
propertyInfos.Add(propInfo.Name, propInfo);
}
PropertyDescriptorCollection baseProps = TypeDescriptor.GetProperties(this, null, true);
if (baseProps != null) {
for (int i = 0; i < baseProps.Count; ++i) {
Debug.Assert(baseProps[i] != null, "Null base prop at location: " + i.ToString(CultureInfo.InvariantCulture));
if (baseProps[i].DesignTimeOnly) {
retProps.Add(baseProps[i]);
continue;
}
string propName = baseProps[i].Name;
PropertyDescriptor prop = null;
PropertyInfo propInfo = (PropertyInfo)propertyInfos[propName];
// We do not support "write-only" properties that some activex controls support.
if (propInfo != null && !propInfo.CanRead)
continue;
if (!properties.ContainsKey(propName)) {
if (propInfo != null) {
Debug.WriteLineIf(AxPropTraceSwitch.TraceVerbose, "Added AxPropertyDescriptor for: " + propName);
prop = new AxPropertyDescriptor(baseProps[i], this);
((AxPropertyDescriptor)prop).UpdateAttributes();
}
else {
Debug.WriteLineIf(AxPropTraceSwitch.TraceVerbose, "Added PropertyDescriptor for: " + propName);
prop = baseProps[i];
}
properties.Add(propName, prop);
retProps.Add(prop);
}
else {
PropertyDescriptor propDesc = (PropertyDescriptor)properties[propName];
Debug.Assert(propDesc != null, "Cannot find cached entry for: " + propName);
AxPropertyDescriptor axPropDesc = propDesc as AxPropertyDescriptor;
if ((propInfo == null && axPropDesc != null) || (propInfo != null && axPropDesc == null)) {
Debug.Fail("Duplicate property with same name: " + propName);
Debug.WriteLineIf(AxPropTraceSwitch.TraceVerbose, "Duplicate property with same name: " + propName);
}
else {
if (axPropDesc != null) {
axPropDesc.UpdateAttributes();
}
retProps.Add(propDesc);
}
}
}
// Filter only the Browsable attribute, since that is the only
// one we mess with.
//
if (attributes != null) {
Attribute browse = null;
foreach(Attribute attr in attributes) {
if (attr is BrowsableAttribute) {
browse = attr;
}
}
if (browse != null) {
ArrayList removeList = null;
foreach(PropertyDescriptor prop in retProps) {
if (prop is AxPropertyDescriptor) {
Attribute attr = prop.Attributes[typeof(BrowsableAttribute)];
if (attr != null && !attr.Equals(browse)) {
if (removeList == null) {
removeList = new ArrayList();
}
removeList.Add(prop);
}
}
}
if (removeList != null) {
foreach(object prop in removeList)
retProps.Remove(prop);
}
}
}
}
PropertyDescriptor[] temp = new PropertyDescriptor[retProps.Count];
retProps.CopyTo(temp, 0);
// Update our stashed values.
//
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Updating stashed values for : " + ((attributes != null) ? attributes.Length.ToString(CultureInfo.InvariantCulture) : "<null>"));
propsStash = new PropertyDescriptorCollection(temp);
attribsStash = attributes;
return propsStash;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetProperties"]/*' />
/// <internalonly/>
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() {
return FillProperties(null);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetProperties1"]/*' />
/// <internalonly/>
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) {
return FillProperties(attributes);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ICustomTypeDescriptor.GetPropertyOwner"]/*' />
/// <internalonly/>
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
Object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) {
return this;
}
private AxPropertyDescriptor GetPropertyDescriptorFromDispid(int dispid) {
Debug.Assert(dispid != NativeMethods.ActiveX.DISPID_UNKNOWN, "Wrong dispid sent to GetPropertyDescriptorFromDispid");
PropertyDescriptorCollection props = FillProperties(null);
foreach (PropertyDescriptor prop in props) {
AxPropertyDescriptor axprop = prop as AxPropertyDescriptor;
if (axprop != null && axprop.Dispid == dispid) {
return axprop;
}
}
return null;
}
#if false
// FxCop: Currently not used
private void CheckThreadingModel() {
#if DEBUG
if (AxIgnoreTMSwitch.Enabled) return;
#endif
if ((flags & AxFlags.IgnoreThreadModel) != 0) return;
bool singleThreaded = true;
new RegistryPermission(PermissionState.Unrestricted).Assert();
try {
try {
using (RegistryKey rk = Registry.ClassesRoot.OpenSubKey("CLSID\\" + clsid.ToString() + "\\InprocServer32", /*writable*/false)) {
object value = rk.GetValue("ThreadingModel");
if (value != null && value is string) {
if (value.Equals("Both")
|| value.Equals("Apartment")
|| value.Equals("Free")) {
singleThreaded = false;
}
}
}
}
catch (Exception t) {
Debug.Fail(t.ToString());
throw new InvalidOperationException(SR.GetString(SR.AXNoThreadInfo));
}
}
finally {
System.Security.CodeAccessPermission.RevertAssert();
}
if (singleThreaded) {
throw new InvalidOperationException(SR.GetString(SR.AXSingleThreaded));
}
}
#endif
private void ActivateAxControl() {
if (QuickActivate()) {
DepersistControl();
}
else {
SlowActivate();
}
SetOcState(OC_RUNNING);
}
private void DepersistFromIPropertyBag(UnsafeNativeMethods.IPropertyBag propBag) {
iPersistPropBag.Load(propBag, null);
}
private void DepersistFromIStream(UnsafeNativeMethods.IStream istream) {
storageType = STG_STREAM;
iPersistStream.Load(istream);
}
private void DepersistFromIStreamInit(UnsafeNativeMethods.IStream istream) {
storageType = STG_STREAMINIT;
iPersistStreamInit.Load(istream);
}
private void DepersistFromIStorage(UnsafeNativeMethods.IStorage storage) {
storageType = STG_STORAGE;
// ASURT 65913 Looks like MapPoint control does not create a valid IStorage
// until some property has changed. Since we end up creating a bogus (empty)
// storage, we end up not being able to re-create a valid one and this would
// fail.
//
if (storage != null) {
int hr = iPersistStorage.Load(storage);
if (hr != NativeMethods.S_OK) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Error trying load depersist from IStorage: " + hr);
}
}
}
private void DepersistControl() {
Freeze(true);
if (ocxState == null) {
// must init new:
//
if (instance is UnsafeNativeMethods.IPersistStreamInit) {
iPersistStreamInit = (UnsafeNativeMethods.IPersistStreamInit) instance;
try {
storageType = STG_STREAMINIT;
iPersistStreamInit.InitNew();
}
catch (Exception e1) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Exception thrown trying to IPersistStreamInit.InitNew(). Is this good?" + e1.ToString());
}
return;
}
if (instance is UnsafeNativeMethods.IPersistStream) {
storageType = STG_STREAM;
iPersistStream = (UnsafeNativeMethods.IPersistStream) instance;
return;
}
if (instance is UnsafeNativeMethods.IPersistStorage) {
storageType = STG_STORAGE;
ocxState = new State(this);
iPersistStorage = (UnsafeNativeMethods.IPersistStorage) instance;
try {
iPersistStorage.InitNew(ocxState.GetStorage());
}
catch (Exception e2) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Exception thrown trying to IPersistStorage.InitNew(). Is this good?" + e2.ToString());
}
return;
}
if (instance is UnsafeNativeMethods.IPersistPropertyBag) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, this + " supports IPersistPropertyBag.");
iPersistPropBag = (UnsafeNativeMethods.IPersistPropertyBag) instance;
try {
iPersistPropBag.InitNew();
}
catch (Exception e1) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Exception thrown trying to IPersistPropertyBag.InitNew(). Is this good?" + e1.ToString());
}
}
Debug.Fail("no implemented persitance interfaces on object");
throw new InvalidOperationException(SR.GetString(SR.UnableToInitComponent));
}
// Otherwise, we have state to deperist from:
switch (ocxState.Type) {
case STG_STREAM:
try {
iPersistStream = (UnsafeNativeMethods.IPersistStream) instance;
DepersistFromIStream(ocxState.GetStream());
}
catch (Exception e) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Exception thrown trying to IPersistStream.DepersistFromIStream(). Is this good?" + e.ToString());
}
break;
case STG_STREAMINIT:
if (instance is UnsafeNativeMethods.IPersistStreamInit) {
try {
iPersistStreamInit = (UnsafeNativeMethods.IPersistStreamInit) instance;
DepersistFromIStreamInit(ocxState.GetStream());
}
catch (Exception e) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Exception thrown trying to IPersistStreamInit.DepersistFromIStreamInit(). Is this good?" + e.ToString());
}
GetControlEnabled();
}
else {
ocxState.Type = STG_STREAM;
DepersistControl();
return;
}
break;
case STG_STORAGE:
try {
iPersistStorage = (UnsafeNativeMethods.IPersistStorage) instance;
DepersistFromIStorage(ocxState.GetStorage());
}
catch (Exception e) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Exception thrown trying to IPersistStorage.DepersistFromIStorage(). Is this good?" + e.ToString());
}
break;
default:
Debug.Fail("unknown storage type.");
throw new InvalidOperationException(SR.GetString(SR.UnableToInitComponent));
}
if (ocxState.GetPropBag() != null) {
try {
iPersistPropBag = (UnsafeNativeMethods.IPersistPropertyBag)instance;
DepersistFromIPropertyBag(ocxState.GetPropBag());
}
catch (Exception e) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Exception thrown trying to IPersistPropertyBag.DepersistFromIPropertyBag(). Is this good?" + e.ToString());
}
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetOcx"]/*' />
/// <devdoc>
/// Returns the IUnknown pointer to the enclosed ActiveX control.
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
public object GetOcx() {
return instance;
}
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
private Object GetOcxCreate() {
if (instance == null) {
CreateInstance();
RealizeStyles();
AttachInterfaces();
oleSite.OnOcxCreate();
}
return instance;
}
private void StartEvents() {
if (!axState[sinkAttached]) {
try {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Creating sink for events...");
CreateSink();
oleSite.StartEvents();
}
catch (Exception t) {
Debug.Fail(t.ToString());
}
axState[sinkAttached] = true;
}
}
private void StopEvents() {
if (axState[sinkAttached]) {
try {
DetachSink();
}
catch (Exception t) {
Debug.Fail(t.ToString());
}
axState[sinkAttached] = false;
}
oleSite.StopEvents();
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.CreateSink"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected virtual void CreateSink() {
// nop... windows forms wrapper will override...
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.DetachSink"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected virtual void DetachSink() {
// nop... windows forms wrapper will override...
}
private bool CanShowPropertyPages() {
if (GetOcState() < OC_RUNNING) return false;
return(GetOcx() is NativeMethods.ISpecifyPropertyPages);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.HasPropertyPages"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public bool HasPropertyPages() {
if (!CanShowPropertyPages()) return false;
NativeMethods.ISpecifyPropertyPages ispp = (NativeMethods.ISpecifyPropertyPages) GetOcx();
try {
NativeMethods.tagCAUUID uuids = new NativeMethods.tagCAUUID();
try {
ispp.GetPages(uuids);
if (uuids.cElems > 0) return true;
}
finally {
if (uuids.pElems != IntPtr.Zero) {
Marshal.FreeCoTaskMem(uuids.pElems);
}
}
}
catch {
}
return false;
}
unsafe private void ShowPropertyPageForDispid(int dispid, Guid guid) {
try {
IntPtr pUnk = Marshal.GetIUnknownForObject(GetOcx());
NativeMethods.OCPFIPARAMS opcparams = new NativeMethods.OCPFIPARAMS();
opcparams.hwndOwner = (ContainingControl == null) ? IntPtr.Zero : ContainingControl.Handle;
opcparams.lpszCaption = Name;
opcparams.ppUnk = (IntPtr) (long) &pUnk;
opcparams.uuid = (IntPtr)(long) &guid;
opcparams.dispidInitial = dispid;
UnsafeNativeMethods.OleCreatePropertyFrameIndirect(opcparams);
}
catch (Exception t) {
Debug.Fail(t.ToString());
throw t;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.MakeDirty"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public void MakeDirty() {
ISite isite = Site;
if (isite == null)
return;
IComponentChangeService ccs = (IComponentChangeService)isite.GetService(typeof(IComponentChangeService));
if (ccs == null)
return;
ccs.OnComponentChanging(this, null);
ccs.OnComponentChanged(this, null, null, null);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ShowPropertyPages"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public void ShowPropertyPages() {
if (ParentInternal == null) return;
if (!ParentInternal.IsHandleCreated) return;
ShowPropertyPages(ParentInternal);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ShowPropertyPages1"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public void ShowPropertyPages(Control control) {
try {
if (!CanShowPropertyPages()) return;
NativeMethods.ISpecifyPropertyPages ispp = (NativeMethods.ISpecifyPropertyPages) GetOcx();
NativeMethods.tagCAUUID uuids = new NativeMethods.tagCAUUID();
try {
ispp.GetPages(uuids);
if (uuids.cElems <= 0) return;
}
catch {
return;
}
// State oldOcxState = OcxState;
IDesignerHost host = null;
if (Site != null)
host = (IDesignerHost)Site.GetService(typeof(IDesignerHost));
DesignerTransaction trans = null;
try {
if (host != null)
trans = host.CreateTransaction(SR.GetString(SR.AXEditProperties));
string name = null;
object o = GetOcx();
IntPtr handle = (ContainingControl == null) ? IntPtr.Zero : ContainingControl.Handle;
SafeNativeMethods.OleCreatePropertyFrame(new HandleRef(this, handle), 0, 0, name, 1, ref o, uuids.cElems, new HandleRef(null, uuids.pElems), Application.CurrentCulture.LCID, 0, IntPtr.Zero);
}
finally {
if (oleSite != null)
((UnsafeNativeMethods.IPropertyNotifySink)oleSite).OnChanged(NativeMethods.MEMBERID_NIL);
if (trans != null)
trans.Commit();
if (uuids.pElems != IntPtr.Zero)
Marshal.FreeCoTaskMem(uuids.pElems);
}
}
catch (Exception t) {
Debug.Fail(t.ToString());
throw t;
}
}
[ResourceExposure(ResourceScope.Process)]
[ResourceConsumption(ResourceScope.Process)]
internal override IntPtr InitializeDCForWmCtlColor (IntPtr dc, int msg)
{
if (isMaskEdit) {
return base.InitializeDCForWmCtlColor(dc, msg);
}
else {
return IntPtr.Zero; // bypass Control's anti-reflect logic
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.WndProc"]/*' />
/// <devdoc>
/// AxHost wndProc. All messages are sent to wndProc after getting filtered
/// through the preProcessMessage function.
/// Certain messages are forwarder directly to the ActiveX control,
/// others are first processed by the wndProc of Control
/// </devdoc>
protected override void WndProc(ref Message m) {
#pragma warning disable 162, 429
// Ignore the warnings generated by the following code (unreachable code, and unreachable expression)
if (false && (axState[manualUpdate] && IsUserMode())) {
DefWndProc(ref m);
return;
}
#pragma warning restore 162, 429
switch (m.Msg) {
// Things we explicitly ignore and pass to the ocx's windproc
case NativeMethods.WM_ERASEBKGND:
case NativeMethods.WM_REFLECT + NativeMethods.WM_NOTIFYFORMAT:
case NativeMethods.WM_SETCURSOR:
case NativeMethods.WM_SYSCOLORCHANGE:
// Some of the MSComCtl controls respond to this message
// to do some custom painting. So, we should just pass this message
// through.
//
case NativeMethods.WM_DRAWITEM:
case NativeMethods.WM_LBUTTONDBLCLK:
case NativeMethods.WM_LBUTTONUP:
case NativeMethods.WM_MBUTTONDBLCLK:
case NativeMethods.WM_MBUTTONUP:
case NativeMethods.WM_RBUTTONDBLCLK:
case NativeMethods.WM_RBUTTONUP:
DefWndProc(ref m);
break;
case NativeMethods.WM_LBUTTONDOWN:
case NativeMethods.WM_MBUTTONDOWN:
case NativeMethods.WM_RBUTTONDOWN:
if (IsUserMode()) {
Focus();
}
DefWndProc(ref m);
break;
case NativeMethods.WM_KILLFOCUS:
{
hwndFocus = m.WParam;
try {
base.WndProc(ref m);
}
finally {
hwndFocus = IntPtr.Zero;
}
break;
}
case NativeMethods.WM_COMMAND:
if (!ReflectMessageInternal(m.LParam, ref m))
DefWndProc(ref m);
break;
case NativeMethods.WM_CONTEXTMENU:
DefWndProc(ref m);
break;
case NativeMethods.WM_DESTROY:
#if DEBUG
if (!OwnWindow()) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "WM_DESTROY naughty control is destroying the window from under us..." + GetType().ToString());
}
#endif
//
// If we are currently in a state of InPlaceActive or above,
// we should first reparent the ActiveX control to our parking
// window before we transition to a state below InPlaceActive.
// Otherwise we face all sorts of problems when we try to
// transition back to a state >= InPlaceActive.
//
if (GetOcState() >= OC_INPLACE) {
UnsafeNativeMethods.IOleInPlaceObject ipo = GetInPlaceObject();
IntPtr hwnd;
if (NativeMethods.Succeeded(ipo.GetWindow(out hwnd))) {
Application.ParkHandle(new HandleRef(ipo, hwnd));
}
}
bool visible = GetState(STATE_VISIBLE);
TransitionDownTo(OC_RUNNING);
DetachAndForward(ref m);
if (visible != GetState(STATE_VISIBLE)) {
SetState(STATE_VISIBLE, visible);
}
break;
case NativeMethods.WM_HELP:
// We want to both fire the event, and let the ocx have the message...
base.WndProc(ref m);
DefWndProc(ref m);
break;
case NativeMethods.WM_KEYUP:
if (axState[processingKeyUp])
break;
axState[processingKeyUp] = true;
try {
if (PreProcessControlMessage(ref m) != PreProcessControlState.MessageProcessed)
DefWndProc(ref m);
}
finally {
axState[processingKeyUp] = false;
}
break;
case NativeMethods.WM_NCDESTROY:
#if DEBUG
if (!OwnWindow()) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "WM_NCDESTROY naughty control is destroying the window from under us..." + GetType().ToString());
}
#endif
// need to detach it now...
DetachAndForward(ref m);
break;
default:
if (m.Msg == REGMSG_MSG) {
m.Result = (IntPtr)REGMSG_RETVAL;
return;
}
// Other things we may care about and we will pass them to the Control's wndProc
base.WndProc(ref m);
break;
}
}
private void DetachAndForward(ref Message m) {
IntPtr handle = GetHandleNoCreate();
DetachWindow();
if (handle != IntPtr.Zero) {
IntPtr wndProc = UnsafeNativeMethods.GetWindowLong(new HandleRef(this, handle), NativeMethods.GWL_WNDPROC);
m.Result = UnsafeNativeMethods.CallWindowProc(wndProc, handle, m.Msg, m.WParam, m.LParam);
}
}
private void DetachWindow() {
if (IsHandleCreated) {
OnHandleDestroyed(EventArgs.Empty);
for (Control c = this; c != null; c = c.ParentInternal) {
/* NOT NEEDED
if (c.GetAxState(STATE_HANDLEHOOK)) {
((IHandleHook)c.Site.GetService(IHandleHook.class)).OnDestroyHandle(GetHandle());
break;
}
*/
}
this.WindowReleaseHandle();
}
}
private void InformOfNewHandle() {
Debug.Assert(IsHandleCreated, "we got to have a handle to be here...");
for (Control c = this; c != null; c = c.ParentInternal) {
/* NOT NEEDED
if (c.GetAxState(STATE_HANDLEHOOK)) {
((IHandleHook)c.Site.GetService(IHandleHook.class)).OnCreateHandle(GetHandle());
break;
}
*/
}
wndprocAddr = UnsafeNativeMethods.GetWindowLong(new HandleRef(this, Handle), NativeMethods.GWL_WNDPROC);
/* NOT NEEDED
SetAxState(STATE_CREATENOTIFIED, true);
*/
}
private void AttachWindow(IntPtr hwnd) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "attaching window for "+this.ToString()+" "+hwnd.ToString());
if (!axState[fFakingWindow]) {
this.WindowAssignHandle(hwnd, axState[assignUniqueID]);
}
UpdateZOrder();
// Get the latest bounds set by the user.
Size setExtent = Size;
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "SetBounds " + setExtent.ToString());
// Get the default bounds set by the ActiveX control.
UpdateBounds();
Size ocxExtent = GetExtent();
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "OcxBounds " + ocxExtent.ToString());
Point location = Location;
// Choose the setBounds unless it is smaller than the default bounds.
if (setExtent.Width < ocxExtent.Width || setExtent.Height < ocxExtent.Height)
Bounds = new Rectangle(location.X, location.Y, ocxExtent.Width, ocxExtent.Height);
else {
Size newSize = SetExtent(setExtent.Width, setExtent.Height);
if (!newSize.Equals(setExtent)) {
Bounds = new Rectangle(location.X, location.Y, newSize.Width, newSize.Height);
}
}
OnHandleCreated(EventArgs.Empty);
InformOfNewHandle();
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.OnHandleCreated"]/*' />
/// <devdoc>
/// Inheriting classes should override this method to find out when the
/// handle has been created.
/// Call base.OnHandleCreated first.
/// </devdoc>
protected override void OnHandleCreated(EventArgs e) {
// ASURT 43741 This is needed to prevent some controls (for e.g. Office Web Components) from
// failing to InPlaceActivate() when they call RegisterDragDrop() but do not call
// OleInitialize(). The EE calls CoInitializeEx() on the thread, but I believe
// that is not good enough for DragDrop.
//
if (Application.OleRequired() != System.Threading.ApartmentState.STA) {
throw new ThreadStateException(SR.GetString(SR.ThreadMustBeSTA));
}
SetAcceptDrops(AllowDrop);
RaiseCreateHandleEvent(e);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ClsidAttribute"]/*' />
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class ClsidAttribute : Attribute {
private String val;
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ClsidAttribute.ClsidAttribute"]/*' />
public ClsidAttribute(String clsid) {
val = clsid;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ClsidAttribute.Value"]/*' />
public String Value {
get {
return val;
}
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="TypeLibraryTimeStampAttribute"]/*' />
[AttributeUsage(AttributeTargets.Assembly, Inherited = false)]
public sealed class TypeLibraryTimeStampAttribute : Attribute {
private DateTime val;
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxImporter.TypeLibraryTimeStampAttribute.TypeLibraryTimeStampAttribute"]/*' />
public TypeLibraryTimeStampAttribute(string timestamp) {
val = DateTime.Parse(timestamp, CultureInfo.InvariantCulture);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxImporter.TypeLibraryTimeStampAttribute.Value"]/*' />
public DateTime Value {
get {
return val;
}
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ConnectionPointCookie"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name="FullTrust")]
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")]
public class ConnectionPointCookie {
private UnsafeNativeMethods.IConnectionPoint connectionPoint;
private int cookie;
internal int threadId;
#if DEBUG
private string callStack;
#endif
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ConnectionPointCookie.ConnectionPointCookie"]/*' />
/// <devdoc>
/// Creates a connection point to of the given interface type.
/// which will call on a managed code sink that implements that interface.
/// </devdoc>
public ConnectionPointCookie(object source, object sink, Type eventInterface)
: this(source, sink, eventInterface, true) {
}
internal ConnectionPointCookie(object source, object sink, Type eventInterface, bool throwException) {
if (source is UnsafeNativeMethods.IConnectionPointContainer) {
UnsafeNativeMethods.IConnectionPointContainer cpc = (UnsafeNativeMethods.IConnectionPointContainer)source;
try {
Guid tmp = eventInterface.GUID;
if (cpc.FindConnectionPoint(ref tmp, out connectionPoint) != NativeMethods.S_OK) {
connectionPoint = null;
}
}
catch {
connectionPoint = null;
}
if (connectionPoint == null) {
if (throwException) {
throw new ArgumentException(SR.GetString(SR.AXNoEventInterface, eventInterface.Name));
}
}
else if (sink == null || !eventInterface.IsInstanceOfType(sink)) {
if (throwException) {
throw new InvalidCastException(SR.GetString(SR.AXNoSinkImplementation, eventInterface.Name));
}
}
else {
int hr = connectionPoint.Advise(sink, ref cookie);
if (hr == NativeMethods.S_OK) {
threadId = Thread.CurrentThread.ManagedThreadId;
}
else {
cookie = 0;
Marshal.ReleaseComObject(connectionPoint);
connectionPoint = null;
if (throwException) {
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.AXNoSinkAdvise, eventInterface.Name), hr));
}
}
}
}
else {
if (throwException) {
throw new InvalidCastException(SR.GetString(SR.AXNoConnectionPointContainer));
}
}
if (connectionPoint == null || cookie == 0) {
if (connectionPoint != null) {
Marshal.ReleaseComObject(connectionPoint);
}
if (throwException) {
throw new ArgumentException(SR.GetString(SR.AXNoConnectionPoint, eventInterface.Name));
}
}
#if DEBUG
new EnvironmentPermission(PermissionState.Unrestricted).Assert();
try {
callStack = Environment.StackTrace;
}
finally {
System.Security.CodeAccessPermission.RevertAssert();
}
#endif
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ConnectionPointCookie.Disconnect"]/*' />
/// <devdoc>
/// Disconnect the current connection point. If the object is not connected,
/// this method will do nothing.
/// </devdoc>
public void Disconnect() {
if (connectionPoint != null && cookie != 0) {
try {
connectionPoint.Unadvise(cookie);
}
catch (Exception ex) {
if (ClientUtils.IsCriticalException(ex)) {
throw;
}
}
finally {
cookie = 0;
}
try {
Marshal.ReleaseComObject(connectionPoint);
}
catch (Exception ex) {
if (ClientUtils.IsCriticalException(ex)) {
throw;
}
}
finally {
connectionPoint = null;
}
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.ConnectionPointCookie.Finalize"]/*' />
/// <internalonly/>
~ConnectionPointCookie(){
if (connectionPoint != null && cookie != 0) {
if (!AppDomain.CurrentDomain.IsFinalizingForUnload()) {
SynchronizationContext context = SynchronizationContext.Current;
if (context == null) {
Debug.Fail("Attempted to disconnect ConnectionPointCookie from the finalizer with no SynchronizationContext.");
}
else {
context.Post(new SendOrPostCallback(AttemptDisconnect), null);
}
}
}
}
void AttemptDisconnect(object trash) {
if (threadId == Thread.CurrentThread.ManagedThreadId) {
Disconnect();
}
else {
Debug.Fail("Attempted to disconnect ConnectionPointCookie from the wrong thread (finalizer).");
}
}
internal bool Connected {
get {
return connectionPoint != null && cookie != 0;
}
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="ActiveXInvokeKind"]/*' />
public enum ActiveXInvokeKind {
/// <include file='doc\AxHost.uex' path='docs/doc[@for="ActiveXInvokeKind.MethodInvoke"]/*' />
MethodInvoke,
/// <include file='doc\AxHost.uex' path='docs/doc[@for="ActiveXInvokeKind.PropertyGet"]/*' />
PropertyGet,
/// <include file='doc\AxHost.uex' path='docs/doc[@for="ActiveXInvokeKind.PropertySet"]/*' />
PropertySet
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="InvalidActiveXStateException"]/*' />
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name="FullTrust")]
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")]
public class InvalidActiveXStateException : Exception {
private string name;
private ActiveXInvokeKind kind;
/// <include file='doc\AxHost.uex' path='docs/doc[@for="InvalidActiveXStateException.InvalidActiveXStateException"]/*' />
public InvalidActiveXStateException(string name, ActiveXInvokeKind kind) {
this.name = name;
this.kind = kind;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="InvalidActiveXStateException.InvalidActiveXStateException2"]/*' />
public InvalidActiveXStateException() {
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="InvalidActiveXStateException.ToString"]/*' />
public override string ToString() {
switch (kind) {
case ActiveXInvokeKind.MethodInvoke:
return SR.GetString(SR.AXInvalidMethodInvoke, name);
case ActiveXInvokeKind.PropertyGet:
return SR.GetString(SR.AXInvalidPropertyGet, name);
case ActiveXInvokeKind.PropertySet:
return SR.GetString(SR.AXInvalidPropertySet, name);
default:
return base.ToString();
}
}
}
// This private class encapsulates all of the ole interfaces so that users
// will not be able to access and call them directly...
/// <devdoc>
/// </devdoc>
private class OleInterfaces
: UnsafeNativeMethods.IOleControlSite, UnsafeNativeMethods.IOleClientSite, UnsafeNativeMethods.IOleInPlaceSite, UnsafeNativeMethods.ISimpleFrameSite, UnsafeNativeMethods.IVBGetControl, UnsafeNativeMethods.IGetVBAObject, UnsafeNativeMethods.IPropertyNotifySink, IReflect, IDisposable {
private AxHost host;
private ConnectionPointCookie connectionPoint;
internal OleInterfaces(AxHost host) {
if (host == null)
throw new ArgumentNullException("host");
this.host = host;
}
private void Dispose(bool disposing) {
if (disposing) {
if (!AppDomain.CurrentDomain.IsFinalizingForUnload()) {
SynchronizationContext context = SynchronizationContext.Current;
if (context == null) {
Debug.Fail("Attempted to disconnect ConnectionPointCookie from the finalizer with no SynchronizationContext.");
}
else {
context.Post(new SendOrPostCallback(AttemptStopEvents), null);
}
}
}
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
internal AxHost GetAxHost() {
return host;
}
internal void OnOcxCreate() {
StartEvents();
}
internal void StartEvents() {
if (connectionPoint != null)
return;
Object nativeObject = host.GetOcx();
try {
connectionPoint = new ConnectionPointCookie(nativeObject, this, typeof(UnsafeNativeMethods.IPropertyNotifySink));
}
catch {
}
}
void AttemptStopEvents(object trash) {
if( connectionPoint == null ){
return;
}
if (connectionPoint.threadId == Thread.CurrentThread.ManagedThreadId) {
StopEvents();
}
else {
Debug.Fail("Attempted to disconnect ConnectionPointCookie from the wrong thread (finalizer).");
}
}
internal void StopEvents() {
if (connectionPoint != null) {
connectionPoint.Disconnect();
connectionPoint = null;
}
}
// IGetVBAObject methods:
int UnsafeNativeMethods.IGetVBAObject.GetObject(ref Guid riid, UnsafeNativeMethods.IVBFormat[] rval, int dwReserved) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in GetObject");
if (rval == null || riid.Equals(Guid.Empty))
return NativeMethods.E_INVALIDARG;
if (riid.Equals(ivbformat_Guid)) {
rval[0] = new VBFormat();
return NativeMethods.S_OK;
}
else {
rval[0] = null;
return NativeMethods.E_NOINTERFACE;
}
}
// IVBGetControl methods:
int UnsafeNativeMethods.IVBGetControl.EnumControls(int dwOleContF, int dwWhich, out UnsafeNativeMethods.IEnumUnknown ppenum) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in EnumControls");
ppenum = null;
ppenum = host.GetParentContainer().EnumControls(host, dwOleContF, dwWhich);
return NativeMethods.S_OK;
}
// ISimpleFrameSite methods:
int UnsafeNativeMethods.ISimpleFrameSite.PreMessageFilter(IntPtr hwnd, int msg, IntPtr wp, IntPtr lp, ref IntPtr plResult, ref int pdwCookie) {
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.ISimpleFrameSite.PostMessageFilter(IntPtr hwnd, int msg, IntPtr wp, IntPtr lp, ref IntPtr plResult, int dwCookie) {
return NativeMethods.S_FALSE;
}
// IReflect methods:
MethodInfo IReflect.GetMethod(String name,BindingFlags bindingAttr,Binder binder, Type[] types,ParameterModifier[] modifiers) {
return null;
}
MethodInfo IReflect.GetMethod(String name,BindingFlags bindingAttr) {
return null;
}
MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr) {
return new MethodInfo[0];
}
FieldInfo IReflect.GetField(String name, BindingFlags bindingAttr) {
return null;
}
FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr) {
return new FieldInfo[0];
}
PropertyInfo IReflect.GetProperty(String name, BindingFlags bindingAttr) {
return null;
}
PropertyInfo IReflect.GetProperty(String name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) {
return null;
}
PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr) {
return new PropertyInfo[0];
}
MemberInfo[] IReflect.GetMember(String name, BindingFlags bindingAttr) {
return new MemberInfo[0];
}
MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr) {
return new MemberInfo[0];
}
Object IReflect.InvokeMember(String name, BindingFlags invokeAttr, Binder binder,
Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters) {
if (name.StartsWith("[DISPID=")) {
int endIndex = name.IndexOf("]");
int dispid = Int32.Parse(name.Substring(8, endIndex - 8), CultureInfo.InvariantCulture);
object ambient = host.GetAmbientProperty(dispid);
if (ambient != null) return ambient;
}
throw E_FAIL;
}
Type IReflect.UnderlyingSystemType {
get {
return null;
}
}
// IOleControlSite methods:
int UnsafeNativeMethods.IOleControlSite.OnControlInfoChanged() {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in OnControlInfoChanged");
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.IOleControlSite.LockInPlaceActive(int fLock) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in LockInPlaceActive");
return NativeMethods.E_NOTIMPL;
}
int UnsafeNativeMethods.IOleControlSite.GetExtendedControl(out object ppDisp) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in GetExtendedControl " + host.ToString());
ppDisp = host.GetParentContainer().GetProxyForControl(host);
if (ppDisp == null)
return NativeMethods.E_NOTIMPL;
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.IOleControlSite.TransformCoords(NativeMethods._POINTL pPtlHimetric, NativeMethods.tagPOINTF pPtfContainer, int dwFlags) {
int hr = SetupLogPixels(false);
if (NativeMethods.Failed(hr))
return hr;
if ((dwFlags & NativeMethods.ActiveX.XFORMCOORDS_HIMETRICTOCONTAINER) != 0) {
if ((dwFlags & NativeMethods.ActiveX.XFORMCOORDS_SIZE) != 0) {
pPtfContainer.x = (float) host.HM2Pix(pPtlHimetric.x, logPixelsX);
pPtfContainer.y = (float) host.HM2Pix(pPtlHimetric.y, logPixelsY);
}
else if ((dwFlags & NativeMethods.ActiveX.XFORMCOORDS_POSITION) != 0) {
pPtfContainer.x = (float) host.HM2Pix(pPtlHimetric.x, logPixelsX);
pPtfContainer.y = (float) host.HM2Pix(pPtlHimetric.y, logPixelsY);
}
else {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose,"\t dwFlags not supported: " + dwFlags);
return NativeMethods.E_INVALIDARG;
}
}
else if ((dwFlags & NativeMethods.ActiveX.XFORMCOORDS_CONTAINERTOHIMETRIC) != 0) {
if ((dwFlags & NativeMethods.ActiveX.XFORMCOORDS_SIZE) != 0) {
pPtlHimetric.x = host.Pix2HM((int)pPtfContainer.x, logPixelsX);
pPtlHimetric.y = host.Pix2HM((int)pPtfContainer.y, logPixelsY);
}
else if ((dwFlags & NativeMethods.ActiveX.XFORMCOORDS_POSITION) != 0) {
pPtlHimetric.x = host.Pix2HM((int)pPtfContainer.x, logPixelsX);
pPtlHimetric.y = host.Pix2HM((int)pPtfContainer.y, logPixelsY);
}
else {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "\t dwFlags not supported: " + dwFlags);
return NativeMethods.E_INVALIDARG;
}
}
else {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "\t dwFlags not supported: " + dwFlags);
return NativeMethods.E_INVALIDARG;
}
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.IOleControlSite.TranslateAccelerator(ref NativeMethods.MSG pMsg, int grfModifiers) {
Debug.Assert(!host.GetAxState(AxHost.siteProcessedInputKey), "Re-entering UnsafeNativeMethods.IOleControlSite.TranslateAccelerator!!!");
host.SetAxState(AxHost.siteProcessedInputKey, true);
Message msg = new Message();
msg.Msg = pMsg.message;
msg.WParam = pMsg.wParam;
msg.LParam = pMsg.lParam;
msg.HWnd = pMsg.hwnd;
try {
bool f = ((Control)host).PreProcessMessage(ref msg);
return f ? NativeMethods.S_OK : NativeMethods.S_FALSE;
}
finally {
host.SetAxState(AxHost.siteProcessedInputKey, false);
}
}
int UnsafeNativeMethods.IOleControlSite.OnFocus(int fGotFocus) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in OnFocus " + ((fGotFocus == 0) ? "lost" : "gained"));
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.IOleControlSite.ShowPropertyFrame() {
if (host.CanShowPropertyPages()) {
host.ShowPropertyPages();
return NativeMethods.S_OK;
}
return NativeMethods.E_NOTIMPL;
}
// IOleClientSite methods:
int UnsafeNativeMethods.IOleClientSite.SaveObject() {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in SaveObject");
return NativeMethods.E_NOTIMPL;
}
int UnsafeNativeMethods.IOleClientSite.GetMoniker(int dwAssign, int dwWhichMoniker, out Object moniker) {
Debug.WriteLineIf(CompModSwitches.ActiveX.TraceInfo, "AxSource:GetMoniker");
moniker = null;
return NativeMethods.E_NOTIMPL;
}
int UnsafeNativeMethods.IOleClientSite.GetContainer(out UnsafeNativeMethods.IOleContainer container) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getContainer");
container = host.GetParentContainer();
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.IOleClientSite.ShowObject() {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in ShowObject");
if (host.GetAxState(AxHost.fOwnWindow)) {
Debug.Fail("we can't be in showobject if we own our window...");
return NativeMethods.S_OK;
}
if (host.GetAxState(AxHost.fFakingWindow)) {
// we really should not be here...
// this means that the ctl inplace deactivated and didn't call on inplace activate before calling showobject
// so we need to destroy our fake window first...
host.DestroyFakeWindow();
// ASURT 46393
// The fact that we have a fake window means that the OCX inplace deactivated when we hid it. It means
// that we have to bring it back from RUNNING to INPLACE so that it can re-create its handle properly.
//
host.TransitionDownTo(OC_LOADED);
host.TransitionUpTo(OC_INPLACE);
}
if (host.GetOcState() < OC_INPLACE)
return NativeMethods.S_OK;
IntPtr hwnd;
if (NativeMethods.Succeeded(host.GetInPlaceObject().GetWindow(out hwnd))) {
if (host.GetHandleNoCreate() != hwnd) {
host.DetachWindow();
if (hwnd != IntPtr.Zero) {
host.AttachWindow(hwnd);
}
}
}
else if (host.GetInPlaceObject() is UnsafeNativeMethods.IOleInPlaceObjectWindowless) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Windowless control.");
throw new InvalidOperationException(SR.GetString(SR.AXWindowlessControl));
}
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.IOleClientSite.OnShowWindow(int fShow) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in OnShowWindow");
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.IOleClientSite.RequestNewObjectLayout() {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in RequestNewObjectLayout");
return NativeMethods.E_NOTIMPL;
}
// IOleInPlaceSite methods:
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.OleInterfaces.GetWindow"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[ResourceExposure(ResourceScope.Process)]
[ResourceConsumption(ResourceScope.Process)]
IntPtr UnsafeNativeMethods.IOleInPlaceSite.GetWindow() {
try {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in GetWindow");
Control parent = host.ParentInternal;
return parent != null ? parent.Handle : IntPtr.Zero;
}
catch (Exception t) {
Debug.Fail(t.ToString());
throw t;
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
int UnsafeNativeMethods.IOleInPlaceSite.ContextSensitiveHelp(int fEnterMode) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in ContextSensitiveHelp");
return NativeMethods.E_NOTIMPL;
}
int UnsafeNativeMethods.IOleInPlaceSite.CanInPlaceActivate() {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in CanInPlaceActivate");
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.IOleInPlaceSite.OnInPlaceActivate() {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in OnInPlaceActivate");
host.SetAxState(AxHost.ownDisposing, false);
host.SetAxState(AxHost.rejectSelection, false);
host.SetOcState(OC_INPLACE);
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.IOleInPlaceSite.OnUIActivate() {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in OnUIActivate for " + host.ToString());
host.SetOcState(OC_UIACTIVE);
host.GetParentContainer().OnUIActivate(host);
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.IOleInPlaceSite.GetWindowContext(out UnsafeNativeMethods.IOleInPlaceFrame ppFrame, out UnsafeNativeMethods.IOleInPlaceUIWindow ppDoc,
NativeMethods.COMRECT lprcPosRect, NativeMethods.COMRECT lprcClipRect, NativeMethods.tagOIFI lpFrameInfo) {
ppDoc = null;
ppFrame = host.GetParentContainer();
FillInRect(lprcPosRect, host.Bounds);
host.GetClipRect(lprcClipRect);
if (lpFrameInfo != null) {
lpFrameInfo.cb = Marshal.SizeOf(typeof(NativeMethods.tagOIFI));
lpFrameInfo.fMDIApp = false;
lpFrameInfo.hAccel = IntPtr.Zero;
lpFrameInfo.cAccelEntries = 0;
lpFrameInfo.hwndFrame = host.ParentInternal.Handle;
}
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.IOleInPlaceSite.Scroll(NativeMethods.tagSIZE scrollExtant) {
try {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in Scroll");
}
catch (Exception t) {
Debug.Fail(t.ToString());
throw t;
}
return(NativeMethods.S_FALSE);
}
int UnsafeNativeMethods.IOleInPlaceSite.OnUIDeactivate(int fUndoable) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in OnUIDeactivate for " + host.ToString());
host.GetParentContainer().OnUIDeactivate(host);
if (host.GetOcState() > OC_INPLACE) {
host.SetOcState(OC_INPLACE);
}
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.IOleInPlaceSite.OnInPlaceDeactivate() {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in OnInPlaceDeactivate");
if (host.GetOcState() == OC_UIACTIVE) {
((UnsafeNativeMethods.IOleInPlaceSite)this).OnUIDeactivate(0);
}
host.GetParentContainer().OnInPlaceDeactivate(host);
host.DetachWindow();
host.SetOcState(OC_RUNNING);
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.IOleInPlaceSite.DiscardUndoState() {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in DiscardUndoState");
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.IOleInPlaceSite.DeactivateAndUndo() {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in DeactivateAndUndo for "+host.ToString());
return host.GetInPlaceObject().UIDeactivate();
}
int UnsafeNativeMethods.IOleInPlaceSite.OnPosRectChange(NativeMethods.COMRECT lprcPosRect) {
// ASURT 68752
// The MediaPlayer control has a AllowChangeDisplaySize property that users
// can set to control size changes at runtime, but the control itself ignores that and sets the new size.
// We prevent this by not allowing controls to call OnPosRectChange(), unless we instantiated the resize.
// visual basic6 does the same.
//
bool useRect = true;
if (AxHost.windowsMediaPlayer_Clsid.Equals(host.clsid))
useRect = host.GetAxState(AxHost.handlePosRectChanged);
if (useRect) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in OnPosRectChange" + lprcPosRect.ToString());
host.GetInPlaceObject().SetObjectRects(lprcPosRect, host.GetClipRect(new NativeMethods.COMRECT()));
host.MakeDirty();
}
else {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Control directly called OnPosRectChange... ignoring the new size");
}
return NativeMethods.S_OK;
}
// IPropertyNotifySink methods
void UnsafeNativeMethods.IPropertyNotifySink.OnChanged(int dispid) {
// Some controls fire OnChanged() notifications when getting values of some properties. ASURT 20190.
// To prevent this kind of recursion, we check to see if we are already inside a OnChanged() call.
//
if (host.NoComponentChangeEvents != 0)
return;
host.NoComponentChangeEvents++;
try {
AxPropertyDescriptor prop = null;
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in OnChanged");
if (dispid != NativeMethods.ActiveX.DISPID_UNKNOWN) {
prop = host.GetPropertyDescriptorFromDispid(dispid);
if (prop != null) {
prop.OnValueChanged(this.host);
if (!prop.SettingValue) {
prop.UpdateTypeConverterAndTypeEditor(true);
}
}
}
else {
// update them all for DISPID_UNKNOWN.
//
PropertyDescriptorCollection props = ((ICustomTypeDescriptor)host).GetProperties();
foreach(PropertyDescriptor p in props) {
prop = p as AxPropertyDescriptor;
if (prop != null && !prop.SettingValue) {
prop.UpdateTypeConverterAndTypeEditor(true);
}
}
}
ISite site = host.Site;
if (site != null) {
IComponentChangeService changeService = (IComponentChangeService)site.GetService(typeof(IComponentChangeService));
if (changeService != null) {
try {
changeService.OnComponentChanging(host, prop);
}
catch (CheckoutException coEx) {
if (coEx == CheckoutException.Canceled) {
return;
}
throw coEx;
}
// Now notify the change service that the change was successful.
//
changeService.OnComponentChanged(host, prop, null, ((prop != null) ? prop.GetValue(host) : null));
}
}
}
catch (Exception t) {
Debug.Fail(t.ToString());
throw t;
}
finally {
host.NoComponentChangeEvents--;
}
}
int UnsafeNativeMethods.IPropertyNotifySink.OnRequestEdit(int dispid) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in OnRequestEdit for "+host.ToString());
return NativeMethods.S_OK;
}
}
private const int HMperInch = 2540;
private int Pix2HM(int pix, int logP) {
return(HMperInch * pix + ( logP >> 1)) / logP;
}
private int HM2Pix(int hm, int logP) {
return(logP * hm + HMperInch / 2) / HMperInch;
}
private bool QuickActivate() {
if (!(instance is UnsafeNativeMethods.IQuickActivate)) return false;
UnsafeNativeMethods.IQuickActivate iqa = (UnsafeNativeMethods.IQuickActivate) instance;
UnsafeNativeMethods.tagQACONTAINER qaContainer = new UnsafeNativeMethods.tagQACONTAINER();
UnsafeNativeMethods.tagQACONTROL qaControl = new UnsafeNativeMethods.tagQACONTROL();
qaContainer.pClientSite = oleSite;
qaContainer.pPropertyNotifySink = oleSite;
// qaContainer.pControlSite = oleSite;
// qaContainer.pAdviseSink = null;
// qaContainer.pUnkEventSink = null;
// qaContainer.pUndoMgr = null;
// qaContainer.pBindHost = null;
// qaContainer.pServiveProvider = null;
// qaContainer.hpal = 0;
qaContainer.pFont = GetIFontFromFont(GetParentContainer().parent.Font);
qaContainer.dwAppearance = 0;
qaContainer.lcid = Application.CurrentCulture.LCID;
Control p = ParentInternal;
if (p != null) {
qaContainer.colorFore = GetOleColorFromColor(p.ForeColor);
qaContainer.colorBack = GetOleColorFromColor(p.BackColor);
}
else {
qaContainer.colorFore = GetOleColorFromColor(SystemColors.WindowText);
qaContainer.colorBack = GetOleColorFromColor(SystemColors.Window);
}
qaContainer.dwAmbientFlags = NativeMethods.ActiveX.QACONTAINER_AUTOCLIP | NativeMethods.ActiveX.QACONTAINER_MESSAGEREFLECT |
NativeMethods.ActiveX.QACONTAINER_SUPPORTSMNEMONICS;
if (IsUserMode()) {
qaContainer.dwAmbientFlags |= NativeMethods.ActiveX.QACONTAINER_USERMODE;
}
else {
// Can't set ui dead becuase MFC controls return NOWHERE on NCHITTEST which
// messes up the designer...
// But, without this the FarPoint SpreadSheet and the Office SpreadSheet
// controls take keyboard input at design time.
//qaContainer.dwAmbientFlags |= NativeMethods.ActiveX.QACONTAINER_UIDEAD;
// qaContainer.dwAmbientFlags |= ActiveX.QACONTAINER_SHOWHATCHING;
}
try {
iqa.QuickActivate(qaContainer, qaControl);
}
catch (Exception t) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Failed to QuickActivate: " + t.ToString());
DisposeAxControl();
return false;
}
miscStatusBits = qaControl.dwMiscStatus;
ParseMiscBits(miscStatusBits);
return true;
}
internal override void DisposeAxControls() {
axState[rejectSelection] = true;
base.DisposeAxControls();
TransitionDownTo(OC_PASSIVE);
}
private bool GetControlEnabled() {
try {
return IsHandleCreated;
}
catch (Exception t) {
Debug.Fail(t.ToString());
return true;
}
}
internal override bool CanSelectCore() {
if (!GetControlEnabled() || axState[rejectSelection]) return false;
return base.CanSelectCore();
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.Dispose"]/*' />
/// <devdoc>
/// Frees all resources assocaited with this control. This method may not be
/// called at runtime. Any resources used by the control should be setup to
/// be released when the control is garbage collected. Inheriting classes should always
/// call base.dispose.
/// </devdoc>
protected override void Dispose(bool disposing) {
if (disposing) {
TransitionDownTo(OC_PASSIVE);
if (newParent != null)
{
newParent.Dispose();
}
if (oleSite != null)
{
oleSite.Dispose();
}
}
base.Dispose(disposing);
}
private bool GetSiteOwnsDeactivation() {
return axState[ownDisposing];
}
private void DisposeAxControl() {
if (GetParentContainer() != null) {
GetParentContainer().RemoveControl(this);
}
TransitionDownTo(OC_RUNNING);
if (GetOcState() == OC_RUNNING) {
GetOleObject().SetClientSite(null);
SetOcState(OC_LOADED);
}
}
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 ParseMiscBits(int bits) {
axState[fOwnWindow] = ((bits & NativeMethods.ActiveX.OLEMISC_INVISIBLEATRUNTIME) != 0) && IsUserMode();
axState[fSimpleFrame] = ((bits & NativeMethods.ActiveX.OLEMISC_SIMPLEFRAME) != 0);
}
private void SlowActivate() {
bool setClientSite = false;
if ((miscStatusBits & NativeMethods.ActiveX.OLEMISC_SETCLIENTSITEFIRST) != 0) {
GetOleObject().SetClientSite(oleSite);
setClientSite = true;
}
DepersistControl();
if (!setClientSite) {
GetOleObject().SetClientSite(oleSite);
}
}
private static NativeMethods.COMRECT FillInRect(NativeMethods.COMRECT dest, Rectangle source) {
dest.left = source.X;
dest.top = source.Y;
dest.right = source.Width + source.X;
dest.bottom = source.Height + source.Y;
return dest;
}
private AxContainer GetParentContainer() {
Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "GetParent Demanded");
IntSecurity.GetParent.Demand();
if (container == null) {
container = AxContainer.FindContainerForControl(this);
}
if (container == null) {
ContainerControl f = ContainingControl;
if (f == null) {
// ContainingCointrol can be null if the AxHost is still not parented to a containerControl
// In everett we used to return a parking window.
// now we just set the containingControl to a dummyValue.
if (newParent == null)
{
newParent = new ContainerControl();
axContainer = newParent.CreateAxContainer();
axContainer.AddControl(this);
}
return axContainer;
}
else {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "calling upon "+f.ToString()+" to create a container");
container = f.CreateAxContainer();
container.AddControl(this);
containingControl = f;
}
}
return container;
}
private UnsafeNativeMethods.IOleControl GetOleControl() {
if (iOleControl == null) {
Debug.Assert(instance != null, "must have the ocx");
iOleControl = (UnsafeNativeMethods.IOleControl) instance;
}
return iOleControl;
}
private UnsafeNativeMethods.IOleInPlaceActiveObject GetInPlaceActiveObject() {
// if our AxContainer was set an external active object then use it.
if(iOleInPlaceActiveObjectExternal != null) {
return iOleInPlaceActiveObjectExternal;
}
// otherwise use our instance.
if (iOleInPlaceActiveObject == null) {
Debug.Assert(instance != null, "must have the ocx");
try {
iOleInPlaceActiveObject = (UnsafeNativeMethods.IOleInPlaceActiveObject)instance;
}
catch (InvalidCastException e) {
Debug.Fail("Invalid cast in GetInPlaceActiveObject: " + e.ToString());
}
}
return iOleInPlaceActiveObject;
}
private UnsafeNativeMethods.IOleObject GetOleObject() {
if (iOleObject == null) {
Debug.Assert(instance != null, "must have the ocx");
iOleObject = (UnsafeNativeMethods.IOleObject) instance;
}
return iOleObject;
}
private UnsafeNativeMethods.IOleInPlaceObject GetInPlaceObject() {
if (iOleInPlaceObject == null) {
Debug.Assert(instance != null, "must have the ocx");
iOleInPlaceObject = (UnsafeNativeMethods.IOleInPlaceObject) instance;
#if DEBUG
if (iOleInPlaceObject is UnsafeNativeMethods.IOleInPlaceObjectWindowless)
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, GetType().FullName + " Can also be a Windowless control.");
#endif //DEBUG
}
return iOleInPlaceObject;
}
private NativeMethods.ICategorizeProperties GetCategorizeProperties() {
if (iCategorizeProperties == null && !axState[checkedCP] && instance != null) {
axState[checkedCP] = true;
if (instance is NativeMethods.ICategorizeProperties) {
iCategorizeProperties = (NativeMethods.ICategorizeProperties) instance;
}
}
return iCategorizeProperties;
}
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;
}
// Mapping functions:
#if false
// FxCop: Currently not used
private static IntPtr CopyPalette(IntPtr hPal) {
if (hPal == IntPtr.Zero) return IntPtr.Zero;
int[] nEntries = new int[1];
UnsafeNativeMethods.GetObject(new HandleRef(null, hPal), 4, nEntries);
IntPtr memory = Marshal.AllocHGlobal(nEntries[0] * 4 + 8);
IntPtr ret = IntPtr.Zero;
try {
Marshal.WriteInt32(memory, 0, 0x300);
Marshal.WriteInt32(memory, 4, nEntries[0]);
SafeNativeMethods.GetPaletteEntries(new HandleRef(null, hPal), 0, nEntries[0], (IntPtr)((long)memory + 8));
ret = SafeNativeMethods.CreatePalette(new HandleRef(null, memory));
}
finally {
Marshal.FreeHGlobal(memory);
}
return ret;
}
#endif
private static Object GetPICTDESCFromPicture(Image image) {
Bitmap bmp = image as Bitmap;
if (bmp != null) {
return new NativeMethods.PICTDESCbmp(bmp);
}
Metafile mf = image as Metafile;
if (mf != null)
{
return new NativeMethods.PICTDESCemf(mf);
}
throw new ArgumentException(SR.GetString(SR.AXUnknownImage), "image");
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetIPictureFromPicture"]/*' />
/// <devdoc>
/// Maps from a System.Drawing.Image to an OLE IPicture
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
protected static object GetIPictureFromPicture(Image image) {
if (image == null) return null;
Object pictdesc = GetPICTDESCFromPicture(image);
return UnsafeNativeMethods.OleCreateIPictureIndirect(pictdesc, ref ipicture_Guid, true);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetIPictureFromCursor"]/*' />
/// <devdoc>
/// Maps from a System.Drawing.Cursor to an OLE IPicture
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
protected static object GetIPictureFromCursor(Cursor cursor) {
if (cursor == null) return null;
NativeMethods.PICTDESCicon pictdesc = new NativeMethods.PICTDESCicon(Icon.FromHandle(cursor.Handle));
return UnsafeNativeMethods.OleCreateIPictureIndirect(pictdesc, ref ipicture_Guid, true);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetIPictureDispFromPicture"]/*' />
/// <devdoc>
/// Maps from a System.Drawing.Image to an OLE IPictureDisp
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
protected static object GetIPictureDispFromPicture(Image image) {
if (image == null) return null;
Object pictdesc = GetPICTDESCFromPicture(image);
return UnsafeNativeMethods.OleCreateIPictureDispIndirect(pictdesc, ref ipictureDisp_Guid, true);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetPictureFromIPicture"]/*' />
/// <devdoc>
/// Maps from an OLE IPicture to a System.Drawing.Image
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
protected static Image GetPictureFromIPicture(object picture) {
if (picture == null) return null;
IntPtr hPal = IntPtr.Zero;
UnsafeNativeMethods.IPicture pict = (UnsafeNativeMethods.IPicture)picture;
int type = pict.GetPictureType();
if (type == NativeMethods.Ole.PICTYPE_BITMAP) {
try {
hPal = pict.GetHPal();
}
catch (COMException) {
}
}
return GetPictureFromParams(pict, pict.GetHandle(), type, hPal, pict.GetWidth(), pict.GetHeight());
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetPictureFromIPictureDisp"]/*' />
/// <devdoc>
/// Maps from an OLE IPictureDisp to a System.Drawing.Image
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
protected static Image GetPictureFromIPictureDisp(object picture) {
if (picture == null) return null;
IntPtr hPal = IntPtr.Zero;
UnsafeNativeMethods.IPictureDisp pict = (UnsafeNativeMethods.IPictureDisp)picture;
int type = pict.PictureType;
if (type == NativeMethods.Ole.PICTYPE_BITMAP) {
try {
hPal = pict.HPal;
}
catch (COMException) {
}
}
return GetPictureFromParams(pict, pict.Handle, type, hPal, pict.Width, pict.Height);
}
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
private static Image GetPictureFromParams(object pict, IntPtr handle, int type, IntPtr paletteHandle, int width, int height) {
switch (type) {
case NativeMethods.Ole.PICTYPE_ICON:
return(Image)(Icon.FromHandle(handle)).Clone();
case NativeMethods.Ole.PICTYPE_METAFILE:
WmfPlaceableFileHeader header = new WmfPlaceableFileHeader();
header.BboxRight = (short)width;
header.BboxBottom = (short)height;
return(Image)(new Metafile(handle, header, false)).Clone();
case NativeMethods.Ole.PICTYPE_ENHMETAFILE:
return(Image)(new Metafile(handle, false)).Clone();
case NativeMethods.Ole.PICTYPE_BITMAP:
return Image.FromHbitmap(handle, paletteHandle);
case NativeMethods.Ole.PICTYPE_NONE:
// MSDN sez this should not be a valid value, but comctl32 returns it...
return null;
case NativeMethods.Ole.PICTYPE_UNINITIALIZED:
return null;
default:
Debug.Fail("Invalid image type "+ type.ToString(CultureInfo.InvariantCulture));
throw new ArgumentException(SR.GetString(SR.AXUnknownImage), "type");
}
}
private static NativeMethods.FONTDESC GetFONTDESCFromFont(Font font) {
NativeMethods.FONTDESC fdesc = null;
if (fontTable == null) {
fontTable = new Hashtable();
}
else {
fdesc = (NativeMethods.FONTDESC)fontTable[font];
}
if (fdesc == null) {
fdesc = new NativeMethods.FONTDESC();
fdesc.lpstrName = font.Name;
fdesc.cySize = (long)(font.SizeInPoints * 10000);
NativeMethods.LOGFONT logfont = new NativeMethods.LOGFONT();
font.ToLogFont(logfont);
fdesc.sWeight = (short) logfont.lfWeight;
fdesc.sCharset = logfont.lfCharSet;
fdesc.fItalic = font.Italic;
fdesc.fUnderline = font.Underline;
fdesc.fStrikethrough = font.Strikeout;
fontTable[font] = fdesc;
}
return fdesc;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetColorFromOleColor"]/*' />
/// <devdoc>
/// Maps from an OLE COLOR to a System.Drawing.Color
/// </devdoc>
[CLSCompliantAttribute(false)]
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected static Color GetColorFromOleColor(uint color) {
return ColorTranslator.FromOle((int)color);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetOleColorFromColor"]/*' />
/// <devdoc>
/// Maps from an System.Drawing.Color to an OLE COLOR
/// </devdoc>
[CLSCompliantAttribute(false)]
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected static uint GetOleColorFromColor(Color color) {
return (uint)ColorTranslator.ToOle(color);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetIFontFromFont"]/*' />
/// <devdoc>
/// Maps from a System.Drawing.Font object to an OLE IFont
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected static object GetIFontFromFont(Font font) {
if (font == null) return null;
if (font.Unit != GraphicsUnit.Point)
throw new ArgumentException(SR.GetString(SR.AXFontUnitNotPoint), "font");
try {
return (UnsafeNativeMethods.IFont)UnsafeNativeMethods.OleCreateIFontIndirect(GetFONTDESCFromFont(font), ref ifont_Guid);
}
catch {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Failed to create IFrom from font: " + font.ToString());
return null;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetFontFromIFont"]/*' />
/// <devdoc>
/// Maps from an OLE IFont to a System.Drawing.Font object
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected static Font GetFontFromIFont(object font) {
if (font == null) return null;
UnsafeNativeMethods.IFont oleFont = (UnsafeNativeMethods.IFont)font;
try {
Font f = Font.FromHfont(oleFont.GetHFont());
if (f.Unit != GraphicsUnit.Point)
f = new Font(f.Name, f.SizeInPoints, f.Style, GraphicsUnit.Point, f.GdiCharSet, f.GdiVerticalFont);
return f;
}
catch (Exception e) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Could not create font." + e.Message);
return DefaultFont;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetIFontDispFromFont"]/*' />
/// <devdoc>
/// Maps from a System.Drawing.Font object to an OLE IFontDisp
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected static object GetIFontDispFromFont(Font font) {
if (font == null) return null;
if (font.Unit != GraphicsUnit.Point)
throw new ArgumentException(SR.GetString(SR.AXFontUnitNotPoint), "font");
SafeNativeMethods.IFontDisp rval = SafeNativeMethods.OleCreateIFontDispIndirect(GetFONTDESCFromFont(font), ref ifontDisp_Guid);
return rval;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetFontFromIFontDisp"]/*' />
/// <devdoc>
/// Maps from an IFontDisp to a System.Drawing.Font object
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected static Font GetFontFromIFontDisp(object font) {
if (font == null)
{
return null;
}
UnsafeNativeMethods.IFont ifont = font as UnsafeNativeMethods.IFont;
if (ifont != null)
{
return GetFontFromIFont(ifont);
}
SafeNativeMethods.IFontDisp oleFont = (SafeNativeMethods.IFontDisp)font;
FontStyle style = FontStyle.Regular;
Font f = null;
try {
if (oleFont.Bold)
style |= FontStyle.Bold;
if (oleFont.Italic)
style |= FontStyle.Italic;
if (oleFont.Underline)
style |= FontStyle.Underline;
if (oleFont.Strikethrough)
style |= FontStyle.Strikeout;
if ((int) oleFont.Weight >= 700) // bold
style |= FontStyle.Bold;
f = new Font(oleFont.Name, (float)oleFont.Size/(float)10000, style, GraphicsUnit.Point, (byte)oleFont.Charset);
return f;
}
catch(Exception e) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Could not create font from: " + oleFont.Name + ". " + e.Message);
return DefaultFont;
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetOADateFromTime"]/*' />
/// <devdoc>
/// Maps from a DateTime object to an OLE DATE (expressed as a double)
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected static double GetOADateFromTime(DateTime time) {
return time.ToOADate();
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.GetTimeFromOADate"]/*' />
/// <devdoc>
/// Maps from an OLE DATE (expressed as a double) to a DateTime object
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected static DateTime GetTimeFromOADate(double date) {
return DateTime.FromOADate(date);
}
/// <devdoc>
/// </devdoc>
/// <internalonly/>
private int Convert2int(Object o, bool xDirection) {
o = ((Array)o).GetValue(0);
// yacky yacky yacky...
// so, usercontrols & other visual basic related controls give us coords as floats in twips
// but mfc controls give us integers as pixels...
if (o.GetType() == typeof(Single)) {
return Twip2Pixel(Convert.ToDouble(o, CultureInfo.InvariantCulture), xDirection);
}
return Convert.ToInt32(o, CultureInfo.InvariantCulture);
}
/// <devdoc>
/// </devdoc>
/// <internalonly/>
private short Convert2short(Object o) {
o = ((Array)o).GetValue(0);
return Convert.ToInt16(o, CultureInfo.InvariantCulture);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.RaiseOnMouseMove"]/*' />
/// <devdoc>
/// </devdoc>
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Advanced), SuppressMessage("Microsoft.Design", "CA1025:ReplaceRepetitiveArgumentsWithParamsArray")]
protected void RaiseOnMouseMove(Object o1, Object o2, Object o3, Object o4) {
RaiseOnMouseMove(Convert2short(o1), Convert2short(o2), Convert2int(o3, true), Convert2int(o4, false));
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.RaiseOnMouseMove1"]/*' />
/// <devdoc>
/// </devdoc>
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected void RaiseOnMouseMove(short button, short shift, float x, float y) {
RaiseOnMouseMove(button, shift, Twip2Pixel((int) x, true), Twip2Pixel((int) y, false));
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.RaiseOnMouseMove2"]/*' />
/// <devdoc>
/// </devdoc>
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected void RaiseOnMouseMove(short button, short shift, int x, int y) {
base.OnMouseMove(new MouseEventArgs( (MouseButtons)(((int)button) << 20), 1, x, y, 0));
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.RaiseOnMouseUp"]/*' />
/// <devdoc>
/// </devdoc>
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Advanced), SuppressMessage("Microsoft.Design", "CA1025:ReplaceRepetitiveArgumentsWithParamsArray")]
protected void RaiseOnMouseUp(Object o1, Object o2, Object o3, Object o4) {
RaiseOnMouseUp(Convert2short(o1), Convert2short(o2), Convert2int(o3, true), Convert2int(o4, false));
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.RaiseOnMouseUp1"]/*' />
/// <devdoc>
/// </devdoc>
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected void RaiseOnMouseUp(short button, short shift, float x, float y) {
RaiseOnMouseUp(button, shift, Twip2Pixel((int) x, true), Twip2Pixel((int) y, false));
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.RaiseOnMouseUp2"]/*' />
/// <devdoc>
/// </devdoc>
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected void RaiseOnMouseUp(short button, short shift, int x, int y) {
base.OnMouseUp(new MouseEventArgs((MouseButtons)(((int)button) << 20), 1, x, y, 0));
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.RaiseOnMouseDown"]/*' />
/// <devdoc>
/// </devdoc>
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Advanced), SuppressMessage("Microsoft.Design", "CA1025:ReplaceRepetitiveArgumentsWithParamsArray")]
protected void RaiseOnMouseDown(Object o1, Object o2, Object o3, Object o4) {
RaiseOnMouseDown(Convert2short(o1), Convert2short(o2), Convert2int(o3, true), Convert2int(o4, false));
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.RaiseOnMouseDown1"]/*' />
/// <devdoc>
/// </devdoc>
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected void RaiseOnMouseDown(short button, short shift, float x, float y) {
RaiseOnMouseDown(button, shift, Twip2Pixel((int) x,true), Twip2Pixel((int) y, false));
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.RaiseOnMouseDown2"]/*' />
/// <devdoc>
/// </devdoc>
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected void RaiseOnMouseDown(short button, short shift, int x, int y) {
base.OnMouseDown(new MouseEventArgs((MouseButtons)(((int)button) << 20), 1, x, y, 0));
}
/// <devdoc>
/// </devdoc>
private class VBFormat : UnsafeNativeMethods.IVBFormat {
// IVBFormat methods:
//
int UnsafeNativeMethods.IVBFormat.Format(ref Object var, IntPtr pszFormat, IntPtr lpBuffer, short cpBuffer, int lcid, short firstD, short firstW, short[] result) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in Format");
if (result == null)
return NativeMethods.E_INVALIDARG;
result[0] = 0;
if (lpBuffer == IntPtr.Zero || cpBuffer < 2)
return NativeMethods.E_INVALIDARG;
IntPtr pbstr = IntPtr.Zero;
int hr = UnsafeNativeMethods.VarFormat(ref var, new HandleRef(null, pszFormat), firstD, firstW, 32 /* VAR_FORMAT_NOSUBSTITUTE */, ref pbstr);
try {
int i = 0;
if (pbstr != IntPtr.Zero) {
short ch = 0;
cpBuffer --;
for (;i < cpBuffer && (ch = Marshal.ReadInt16(pbstr, i * 2)) != 0; i++) {
Marshal.WriteInt16(lpBuffer, i * 2, ch);
}
}
Marshal.WriteInt16(lpBuffer, i * 2, (short) 0);
result[0] = (short) i;
}
finally {
SafeNativeMethods.SysFreeString(new HandleRef(null, pbstr));
}
return NativeMethods.S_OK;
}
}
/// <devdoc>
/// </devdoc>
internal class EnumUnknown : UnsafeNativeMethods.IEnumUnknown {
private Object[] arr;
private int loc;
private int size;
internal EnumUnknown(Object[] arr) {
//if (AxHTraceSwitch.TraceVerbose) Debug.WriteObject(arr);
this.arr = arr;
loc = 0;
size = (arr == null) ? 0 : arr.Length;
}
private EnumUnknown(Object[] arr, int loc) : this(arr) {
this.loc = loc;
}
unsafe int UnsafeNativeMethods.IEnumUnknown.Next(int celt, IntPtr rgelt, IntPtr pceltFetched) {
if (pceltFetched != IntPtr.Zero)
Marshal.WriteInt32(pceltFetched, 0, 0);
if (celt < 0) {
return NativeMethods.E_INVALIDARG;
}
int fetched = 0;
if (loc >= size) {
fetched = 0;
}
else {
for (; loc < size && fetched < celt; ++loc) {
if (arr[loc] != null) {
Marshal.WriteIntPtr(rgelt, Marshal.GetIUnknownForObject(arr[loc]));
rgelt = (IntPtr)((long)rgelt + (long)sizeof(IntPtr));
++fetched;
}
}
}
if (pceltFetched != IntPtr.Zero)
Marshal.WriteInt32(pceltFetched, 0, fetched);
if (fetched != celt) {
return(NativeMethods.S_FALSE);
}
return NativeMethods.S_OK;
}
int UnsafeNativeMethods.IEnumUnknown.Skip(int celt) {
loc += celt;
if (loc >= size) {
return(NativeMethods.S_FALSE);
}
return NativeMethods.S_OK;
}
void UnsafeNativeMethods.IEnumUnknown.Reset() {
loc = 0;
}
void UnsafeNativeMethods.IEnumUnknown.Clone(out UnsafeNativeMethods.IEnumUnknown ppenum) {
ppenum = new EnumUnknown(arr, loc);
}
}
/// <devdoc>
/// </devdoc>
internal class AxContainer : UnsafeNativeMethods.IOleContainer, UnsafeNativeMethods.IOleInPlaceFrame, IReflect {
internal ContainerControl parent;
private IContainer assocContainer; // associated IContainer...
// the assocContainer may be null, in which case all this container does is
// forward [de]activation messages to the requisite container...
private AxHost siteUIActive;
private AxHost siteActive;
private bool formAlreadyCreated = false;
private Hashtable containerCache = new Hashtable(); // name -> Control
private int lockCount = 0;
private Hashtable components = null; // Control -> any
private Hashtable proxyCache = null;
private AxHost ctlInEditMode = null;
private const int GC_CHILD = 0x1;
private const int GC_LASTSIBLING = 0x2;
private const int GC_FIRSTSIBLING = 0x4;
private const int GC_CONTAINER = 0x20;
private const int GC_PREVSIBLING = 0x40;
private const int GC_NEXTSIBLING = 0x80;
internal AxContainer(ContainerControl parent) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in constructor. Parent created : "+parent.Created.ToString());
this.parent = parent;
if (parent.Created) FormCreated();
}
// IReflect methods:
MethodInfo IReflect.GetMethod(String name,BindingFlags bindingAttr,Binder binder, Type[] types,ParameterModifier[] modifiers) {
return null;
}
MethodInfo IReflect.GetMethod(String name,BindingFlags bindingAttr) {
return null;
}
MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr) {
return new MethodInfo[0];
}
FieldInfo IReflect.GetField(String name, BindingFlags bindingAttr) {
return null;
}
FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr) {
return new FieldInfo[0];
}
PropertyInfo IReflect.GetProperty(String name, BindingFlags bindingAttr) {
return null;
}
PropertyInfo IReflect.GetProperty(String name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) {
return null;
}
PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr) {
return new PropertyInfo[0];
}
MemberInfo[] IReflect.GetMember(String name, BindingFlags bindingAttr) {
return new MemberInfo[0];
}
MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr) {
return new MemberInfo[0];
}
Object IReflect.InvokeMember(String name, BindingFlags invokeAttr, Binder binder,
Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters) {
foreach(DictionaryEntry e in containerCache) {
string ctlName = GetNameForControl((Control)e.Key);
if (ctlName.Equals(name)) {
return GetProxyForControl((Control)e.Value);
}
}
throw E_FAIL;
}
Type IReflect.UnderlyingSystemType {
get {
return null;
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
internal UnsafeNativeMethods.IExtender GetProxyForControl(Control ctl) {
UnsafeNativeMethods.IExtender rval = null;
if (proxyCache == null) {
proxyCache = new Hashtable();
}
else {
rval = (UnsafeNativeMethods.IExtender) proxyCache[ctl];
}
if (rval == null) {
if (ctl != parent && !GetControlBelongs(ctl)) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "!parent || !belongs NYI");
AxContainer c = FindContainerForControl(ctl);
if (c != null) {
rval = new ExtenderProxy(ctl, c);
}
else {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "unable to find proxy, returning null");
return null;
}
}
else {
rval = new ExtenderProxy(ctl, this);
}
proxyCache.Add(ctl, rval);
}
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "found proxy "+rval.ToString());
return rval;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
internal string GetNameForControl(Control ctl) {
string name = (ctl.Site != null) ? ctl.Site.Name : ctl.Name;
return (name == null) ? "" : name;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
internal Object GetProxyForContainer() {
return this;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
internal void AddControl(Control ctl) {
//
lock(this) {
if (containerCache.Contains(ctl))
throw new ArgumentException(SR.GetString(SR.AXDuplicateControl, GetNameForControl(ctl)), "ctl");
containerCache.Add(ctl, ctl);
if (assocContainer == null) {
ISite site = ctl.Site;
if (site != null) {
assocContainer = site.Container;
IComponentChangeService ccs = (IComponentChangeService)site.GetService(typeof(IComponentChangeService));
if (ccs != null) {
ccs.ComponentRemoved += new ComponentEventHandler(this.OnComponentRemoved);
}
}
}
else {
#if DEBUG
ISite site = ctl.Site;
if (site != null && assocContainer != site.Container) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "mismatch between assoc container & added control");
}
#endif
}
}
}
internal void RemoveControl(Control ctl) {
//
lock(this) {
if (containerCache.Contains(ctl)) {
containerCache.Remove(ctl);
}
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
private void LockComponents() {
lockCount++;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
private void UnlockComponents() {
lockCount--;
if (lockCount == 0) {
components = null;
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
internal UnsafeNativeMethods.IEnumUnknown EnumControls(Control ctl, int dwOleContF, int dwWhich) {
GetComponents();
LockComponents();
try {
ArrayList l = null;
bool selected = (dwWhich & NativeMethods.ActiveX.GC_WCH_FSELECTED) != 0;
bool reverse = (dwWhich & NativeMethods.ActiveX.GC_WCH_FREVERSEDIR) != 0;
// Note that visual basic actually ignores the next/prev flags... we will not
bool onlyNext = (dwWhich & NativeMethods.ActiveX.GC_WCH_FONLYNEXT) != 0;
bool onlyPrev = (dwWhich & NativeMethods.ActiveX.GC_WCH_FONLYPREV) != 0;
dwWhich = dwWhich & ~(NativeMethods.ActiveX.GC_WCH_FSELECTED | NativeMethods.ActiveX.GC_WCH_FREVERSEDIR |
NativeMethods.ActiveX.GC_WCH_FONLYNEXT | NativeMethods.ActiveX.GC_WCH_FONLYPREV);
if (onlyNext && onlyPrev) {
Debug.Fail("onlyNext && onlyPrev are both set!");
throw E_INVALIDARG;
}
if (dwWhich == NativeMethods.ActiveX.GC_WCH_CONTAINER || dwWhich == NativeMethods.ActiveX.GC_WCH_CONTAINED) {
if (onlyNext || onlyPrev) {
Debug.Fail("GC_WCH_FONLYNEXT or FONLYPREV used with CONTANER or CONATINED");
throw E_INVALIDARG;
}
}
int first = 0;
int last = -1; // meaning all
Control[] ctls = null;
switch (dwWhich) {
default:
Debug.Fail("Bad GC_WCH");
throw E_INVALIDARG;
case NativeMethods.ActiveX.GC_WCH_CONTAINED:
ctls = ctl.GetChildControlsInTabOrder(false);
ctl = null;
break;
case NativeMethods.ActiveX.GC_WCH_SIBLING:
Control p = ctl.ParentInternal;
if (p != null) {
ctls = p.GetChildControlsInTabOrder(false);
if (onlyPrev) {
last = ctl.TabIndex;
}
else if (onlyNext) {
first = ctl.TabIndex + 1;
}
}
else {
ctls = new Control[0];
}
ctl = null;
break;
case NativeMethods.ActiveX.GC_WCH_CONTAINER:
l = new ArrayList();
MaybeAdd(l, ctl, selected, dwOleContF, false);
while (ctl != null) {
AxContainer cont = FindContainerForControl(ctl);
if (cont != null) {
MaybeAdd(l, cont.parent, selected, dwOleContF, true);
ctl = cont.parent;
}
else {
break;
}
}
break;
case NativeMethods.ActiveX.GC_WCH_ALL:
Hashtable htbl = GetComponents();
ctls = new Control[htbl.Keys.Count];
htbl.Keys.CopyTo(ctls, 0);
ctl = parent;
break;
}
if (l == null) {
l = new ArrayList();
if (last == -1 && ctls != null) last = ctls.Length;
if (ctl != null) MaybeAdd(l, ctl, selected, dwOleContF, false);
for (int i = first; i < last; i++) {
MaybeAdd(l, ctls[i], selected, dwOleContF, false);
}
}
Object[] rval = new Object[l.Count];
l.CopyTo(rval, 0);
if (reverse) {
for (int i = 0, j = rval.Length - 1; i < j; i++, j--) {
Object temp = rval[i];
rval[i] = rval[j];
rval[j] = temp;
}
}
return new EnumUnknown(rval);
}
finally {
UnlockComponents();
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
private void MaybeAdd(ArrayList l, Control ctl, bool selected, int dwOleContF, bool ignoreBelong) {
if (!ignoreBelong && ctl != parent && !GetControlBelongs(ctl)) return;
if (selected) {
ISelectionService iss = GetSelectionService(ctl);
if (iss == null || !iss.GetComponentSelected(this)) return;
}
AxHost hostctl = ctl as AxHost;
if (hostctl != null && (dwOleContF & NativeMethods.ActiveX.OLECONTF_EMBEDDINGS) != 0) {
l.Add(hostctl.GetOcx());
}
else if ((dwOleContF & NativeMethods.ActiveX.OLECONTF_OTHERS) != 0) {
Object item = GetProxyForControl(ctl);
if (item != null) l.Add(item);
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
private void FillComponentsTable(IContainer container) {
if (container != null) {
ComponentCollection comps = container.Components;
if (comps != null) {
components = new Hashtable();
foreach (IComponent comp in comps) {
if (comp is Control && comp != parent && comp.Site != null) {
components.Add(comp, comp);
}
}
return;
}
}
Debug.Assert(parent.Site == null, "Parent is sited but we could not find IContainer!!!");
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Did not find a container in FillComponentsTable!!!");
bool checkHashTable = true;
Control[] ctls = new Control[containerCache.Values.Count];
containerCache.Values.CopyTo(ctls, 0);
if (ctls != null) {
if (ctls.Length > 0 && components == null) {
components = new Hashtable();
checkHashTable = false;
}
for (int i = 0; i < ctls.Length; i ++) {
if (checkHashTable && !components.Contains(ctls[i])) {
components.Add(ctls[i], ctls[i]);
}
}
}
GetAllChildren(this.parent);
}
private void GetAllChildren(Control ctl) {
if (ctl == null)
return;
if (components == null) {
components = new Hashtable();
}
if (ctl != this.parent && !components.Contains(ctl))
components.Add(ctl, ctl);
foreach(Control c in ctl.Controls) {
GetAllChildren(c);
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
private Hashtable GetComponents() {
return GetComponents(GetParentsContainer());
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
private Hashtable GetComponents(IContainer cont) {
if (lockCount == 0) {
FillComponentsTable(cont);
}
return components;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
private bool GetControlBelongs(Control ctl) {
Hashtable comps = GetComponents();
return comps[ctl] != null;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
private IContainer GetParentIsDesigned() {
ISite site = parent.Site;
if (site != null && site.DesignMode) return site.Container;
return null;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
private IContainer GetParentsContainer() {
IContainer rval = GetParentIsDesigned();
Debug.Assert(rval == null || assocContainer == null || (rval == assocContainer),
"mismatch between getIPD & aContainer");
return rval == null ? assocContainer : rval;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
private bool RegisterControl(AxHost ctl) {
ISite site = ctl.Site;
if (site != null) {
IContainer cont = site.Container;
if (cont != null) {
if (assocContainer != null) {
return cont == assocContainer;
}
else {
assocContainer = cont;
IComponentChangeService ccs = (IComponentChangeService)site.GetService(typeof(IComponentChangeService));
if (ccs != null) {
ccs.ComponentRemoved += new ComponentEventHandler(this.OnComponentRemoved);
}
return true;
}
}
}
return false;
}
private void OnComponentRemoved(object sender, ComponentEventArgs e) {
Control c = e.Component as Control;
if (sender == assocContainer && c != null) {
RemoveControl(c);
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
internal static AxContainer FindContainerForControl(Control ctl) {
AxHost axctl = ctl as AxHost;
if (axctl != null)
{
if (axctl.container != null) return axctl.container;
ContainerControl f = axctl.ContainingControl;
if (f != null) {
AxContainer container = f.CreateAxContainer();
if (container.RegisterControl(axctl)) {
container.AddControl(axctl);
return container;
}
}
}
return null;
}
#if false
// FxCop: Currently not used
private void OnOldActiveControl(Control valueOld, Control valueNew) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "onOAC called with old: "+valueOld.ToString()+" new: "+valueNew.ToString());
if (!(valueOld is AxHost)) return;
AxContainer c = FindContainerForControl(valueOld);
if (c != null) {
c.OnOldActiveControlInternal(valueOld);
}
else {
Debug.Fail("control w/o a container... pretty bad..."+valueOld.ToString());
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
// FxCop: Currently not used
private void OnOldActiveControlInternal(Control valueOld) {
if (siteUIActive == valueOld) siteUIActive.UiDeactivate();
}
// FxCop: Currently not used
private void OnNewActiveControl(Control value) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "onNAC called with new: "+value.ToString());
if (!(value is AxHost)) return;
AxContainer c = FindContainerForControl(value);
if (c != null) {
c.OnNewActiveControlInternal((AxHost)value);
}
else {
Debug.Fail("control w/o a container... pretty bad..."+value.ToString());
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
// FxCop: Currently not used
private void OnNewActiveControlInternal(AxHost value) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "New active control. siteUIActive is" +siteUIActive.ToString()+" Control is "+value.ToString());
if (siteUIActive != null && siteUIActive != value) {
Debug.Fail("we should not have an ui active site on this container!"+parent.ToString());
siteUIActive.UiDeactivate();
}
#if DEBUG
if (siteUIActive != null && siteUIActive != value) Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Why is "+siteUIActive.ToString()+" still active?");
if (!value.CanUIActivate) Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "why can't "+value.ToString()+" be uiactivated?");
#endif
if (siteUIActive == null && value.CanUIActivate) {
// we need to uiactivate it ourselves...
try {
((AxHost)value).UiActivate();
}
catch (Exception e) {
Debug.Fail(e.ToString());
}
}
#if DEBUG
if (siteUIActive != parent.ActiveControl && value.CanUIActivate) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "form's active control is "+parent.ActiveControl.ToString());
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "could not reconcile active controls... bad things loom on the horizon...");
}
#endif
if (siteUIActive == null) {
// so now the form thinks that value is the active control but it's not ui active...
// this can often lead to bad things unless we are carefull...
siteActive = value;
// basically, when siteActive goes inplacedeactivate, we need to treat it the same as a
// siteuiactive going uiactivedeactivate...
}
}
#endif
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
internal void OnInPlaceDeactivate(AxHost site) {
if (siteActive == site) {
siteActive = null;
if (site.GetSiteOwnsDeactivation()) {
parent.ActiveControl = null;
}
else {
// we need to tell the form to switch activation to the next thingie...
Debug.Fail("what pathological control is calling inplacedeactivate by itself?");
}
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
internal void OnUIDeactivate(AxHost site) {
#if DEBUG
if (siteUIActive != null)
Debug.Assert(siteUIActive == site, "deactivating when not active...");
#endif // DEBUG
siteUIActive = null;
site.RemoveSelectionHandler();
site.SetSelectionStyle(1);
site.editMode = EDITM_NONE;
if (site.GetSiteOwnsDeactivation()) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, " our site owns deactivation ");
ContainerControl f = site.ContainingControl;
Debug.Assert(f != null, "a control has to be on a ContainerControl...");
if (f != null) {
// f.setActiveControl(null);
}
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
internal void OnUIActivate(AxHost site) {
// The ShDocVw control repeatedly calls OnUIActivate() with the same
// site. This causes the assert below to fire.
//
if (siteUIActive == site)
return;
if (siteUIActive != null && siteUIActive != site) {
AxHost tempSite = siteUIActive;
bool ownDisposing = tempSite.GetAxState(AxHost.ownDisposing);
try {
tempSite.SetAxState(AxHost.ownDisposing, true);
tempSite.GetInPlaceObject().UIDeactivate();
}
finally {
tempSite.SetAxState(AxHost.ownDisposing, ownDisposing);
}
}
site.AddSelectionHandler();
Debug.Assert(siteUIActive == null, "Object did not call OnUIDeactivate");
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "active Object is now "+site.ToString());
siteUIActive = site;
ContainerControl f = site.ContainingControl;
Debug.Assert(f != null, "a control has to be on a ContainerControl...");
if (f != null) {
f.ActiveControl = site;
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
private void ListAxControls(ArrayList list, bool fuseOcx) {
Hashtable components = GetComponents();
if (components == null) return;
Control[] ctls = new Control[components.Keys.Count];
components.Keys.CopyTo(ctls, 0);
if (ctls != null) {
for (int i = 0; i < ctls.Length; i++) {
Control ctl = ctls[i];
AxHost hostctl = ctl as AxHost;
if (hostctl != null) {
if (fuseOcx) {
list.Add(hostctl.GetOcx());
}
else {
list.Add(ctl);
}
}
}
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
internal void ControlCreated(AxHost invoker) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in controlCreated for "+invoker.ToString()+" fAC: "+formAlreadyCreated.ToString());
if (formAlreadyCreated) {
if (invoker.IsUserMode() && invoker.AwaitingDefreezing()) {
invoker.Freeze(false);
}
}
else {
// the form will be created in the future
parent.CreateAxContainer();
}
}
internal void FormCreated() {
if (formAlreadyCreated) return;
formAlreadyCreated = true;
ArrayList l = new ArrayList();
ListAxControls(l, false);
AxHost[] axControls = new AxHost[l.Count];
l.CopyTo(axControls, 0);
for (int i = 0; i < axControls.Length; i++) {
AxHost control = axControls[i];
if (control.GetOcState() >= OC_RUNNING && control.IsUserMode() && control.AwaitingDefreezing()) {
control.Freeze(false);
}
}
}
// IOleContainer methods:
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxContainer.ParseDisplayName"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
int UnsafeNativeMethods.IOleContainer.ParseDisplayName(Object pbc, string pszDisplayName, int[] pchEaten, Object[] ppmkOut) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in ParseDisplayName");
if (ppmkOut != null)
ppmkOut[0] = null;
return NativeMethods.E_NOTIMPL;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxContainer.EnumObjects"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
int UnsafeNativeMethods.IOleContainer.EnumObjects(int grfFlags, out UnsafeNativeMethods.IEnumUnknown ppenum) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in EnumObjects");
ppenum = null;
if ((grfFlags & 1) != 0) { // 1 == OLECONTF_EMBEDDINGS
Debug.Assert(parent != null, "gotta have it...");
ArrayList list = new ArrayList();
ListAxControls(list, true);
if (list.Count > 0) {
Object[] temp = new Object[list.Count];
list.CopyTo(temp, 0);
ppenum = new EnumUnknown(temp);
return NativeMethods.S_OK;
}
}
ppenum = new EnumUnknown(null);
return NativeMethods.S_OK;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxContainer.LockContainer"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
int UnsafeNativeMethods.IOleContainer.LockContainer(bool fLock) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in LockContainer");
return NativeMethods.E_NOTIMPL;
}
// IOleInPlaceFrame methods:
IntPtr UnsafeNativeMethods.IOleInPlaceFrame.GetWindow() {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in GetWindow");
return parent.Handle;
}
int UnsafeNativeMethods.IOleInPlaceFrame.ContextSensitiveHelp(int fEnterMode) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in ContextSensitiveHelp");
return NativeMethods.S_OK;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxContainer.GetBorder"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
int UnsafeNativeMethods.IOleInPlaceFrame.GetBorder(NativeMethods.COMRECT lprectBorder) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in GetBorder");
return NativeMethods.E_NOTIMPL;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxContainer.RequestBorderSpace"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
int UnsafeNativeMethods.IOleInPlaceFrame.RequestBorderSpace(NativeMethods.COMRECT pborderwidths) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in RequestBorderSpace");
return NativeMethods.E_NOTIMPL;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxContainer.SetBorderSpace"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
int UnsafeNativeMethods.IOleInPlaceFrame.SetBorderSpace(NativeMethods.COMRECT pborderwidths) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in SetBorderSpace");
return NativeMethods.E_NOTIMPL;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
internal void OnExitEditMode(AxHost ctl) {
Debug.Assert(ctlInEditMode == null || ctlInEditMode == ctl, "who is exiting edit mode?");
if (ctlInEditMode == null || ctlInEditMode != ctl) return;
ctlInEditMode = null;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxContainer.SetActiveObject"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
int UnsafeNativeMethods.IOleInPlaceFrame.SetActiveObject(UnsafeNativeMethods.IOleInPlaceActiveObject pActiveObject, string pszObjName) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in SetActiveObject " + ((pszObjName == null) ? "<null>" : pszObjName));
if (siteUIActive != null) {
if (siteUIActive.iOleInPlaceActiveObjectExternal != pActiveObject) {
if (siteUIActive.iOleInPlaceActiveObjectExternal != null) {
Marshal.ReleaseComObject(siteUIActive.iOleInPlaceActiveObjectExternal);
}
siteUIActive.iOleInPlaceActiveObjectExternal = pActiveObject;
}
}
if (pActiveObject == null) {
if (ctlInEditMode != null) {
ctlInEditMode.editMode = EDITM_NONE;
ctlInEditMode = null;
}
return NativeMethods.S_OK;
}
AxHost ctl = null;
if (pActiveObject is UnsafeNativeMethods.IOleObject) {
UnsafeNativeMethods.IOleObject oleObject = (UnsafeNativeMethods.IOleObject) pActiveObject;
UnsafeNativeMethods.IOleClientSite clientSite = null;
try {
clientSite = oleObject.GetClientSite();
if (clientSite is OleInterfaces) {
ctl = ((OleInterfaces)(clientSite)).GetAxHost();
}
}
catch (COMException t) {
Debug.Fail(t.ToString());
}
if (ctlInEditMode != null) {
Debug.Fail("control " + ctlInEditMode.ToString() + " did not reset its edit mode to null");
ctlInEditMode.SetSelectionStyle(1);
ctlInEditMode.editMode = EDITM_NONE;
}
if (ctl == null) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "control w/o a valid site called setactiveobject");
ctlInEditMode = null;
}
else {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "resolved to " + ctl.ToString());
if (!ctl.IsUserMode()) {
ctlInEditMode = ctl;
ctl.editMode = EDITM_OBJECT;
ctl.AddSelectionHandler();
ctl.SetSelectionStyle(2);
}
}
}
return NativeMethods.S_OK;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxContainer.InsertMenus"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
int UnsafeNativeMethods.IOleInPlaceFrame.InsertMenus(IntPtr hmenuShared, NativeMethods.tagOleMenuGroupWidths lpMenuWidths) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in InsertMenus");
return NativeMethods.S_OK;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxContainer.SetMenu"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
int UnsafeNativeMethods.IOleInPlaceFrame.SetMenu(IntPtr hmenuShared, IntPtr holemenu, IntPtr hwndActiveObject) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in SetMenu");
return NativeMethods.E_NOTIMPL;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxContainer.RemoveMenus"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
int UnsafeNativeMethods.IOleInPlaceFrame.RemoveMenus(IntPtr hmenuShared) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in RemoveMenus");
return NativeMethods.E_NOTIMPL;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxContainer.SetStatusText"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
int UnsafeNativeMethods.IOleInPlaceFrame.SetStatusText(string pszStatusText) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in SetStatusText");
return NativeMethods.E_NOTIMPL;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxContainer.EnableModeless"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
int UnsafeNativeMethods.IOleInPlaceFrame.EnableModeless(bool fEnable) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in EnableModeless");
return NativeMethods.E_NOTIMPL;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxContainer.TranslateAccelerator"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
int UnsafeNativeMethods.IOleInPlaceFrame.TranslateAccelerator(ref NativeMethods.MSG lpmsg, short wID) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in IOleInPlaceFrame.TranslateAccelerator");
return NativeMethods.S_FALSE;
}
// EXPOSED
/// <devdoc>
/// </devdoc>
private class ExtenderProxy : UnsafeNativeMethods.IExtender, UnsafeNativeMethods.IVBGetControl, UnsafeNativeMethods.IGetVBAObject, UnsafeNativeMethods.IGetOleObject, IReflect {
private WeakReference pRef;
private WeakReference pContainer;
internal ExtenderProxy(Control principal, AxContainer container) {
pRef = new WeakReference(principal);
pContainer = new WeakReference(container);
}
private Control GetP() {
return(Control) pRef.Target;
}
private AxContainer GetC() {
return(AxContainer) pContainer.Target;
}
int UnsafeNativeMethods.IVBGetControl.EnumControls(int dwOleContF, int dwWhich, out UnsafeNativeMethods.IEnumUnknown ppenum) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in EnumControls for proxy");
ppenum = GetC().EnumControls(GetP(), dwOleContF, dwWhich);
return NativeMethods.S_OK;
}
object UnsafeNativeMethods.IGetOleObject.GetOleObject(ref Guid riid) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in GetOleObject for proxy");
if (!riid.Equals(ioleobject_Guid))
throw E_INVALIDARG;
Control ctl = GetP();
if (ctl != null && ctl is AxHost) {
return ((AxHost)ctl).GetOcx();
}
throw E_FAIL;
}
int UnsafeNativeMethods.IGetVBAObject.GetObject(ref Guid riid, UnsafeNativeMethods.IVBFormat[] rval, int dwReserved) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in GetObject for proxy");
if (rval == null || riid.Equals(Guid.Empty))
return NativeMethods.E_INVALIDARG;
if (riid.Equals(ivbformat_Guid)) {
rval[0] = new VBFormat();
return NativeMethods.S_OK;
}
else {
rval[0] = null;
return NativeMethods.E_NOINTERFACE;
}
}
public int Align {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getAlign for proxy for "+ GetP().ToString());
int rval = (int)((Control)GetP()).Dock;
if (rval < NativeMethods.ActiveX.ALIGN_MIN || rval > NativeMethods.ActiveX.ALIGN_MAX) {
rval = NativeMethods.ActiveX.ALIGN_NO_CHANGE;
}
return rval;
}
set {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in setAlign for proxy for "+ GetP().ToString()+" "+
value.ToString(CultureInfo.InvariantCulture));
GetP().Dock = (DockStyle)value;
}
}
public UInt32 BackColor {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getBackColor for proxy for "+ GetP().ToString());
return AxHost.GetOleColorFromColor(((Control)GetP()).BackColor);
}
set {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in setBackColor for proxy for "+ GetP().ToString()+" "+
value.ToString(CultureInfo.InvariantCulture));
GetP().BackColor = AxHost.GetColorFromOleColor(value);
}
}
public bool Enabled {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getEnabled for proxy for "+ GetP().ToString());
return GetP().Enabled;
}
set {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in setEnabled for proxy for "+ GetP().ToString()+" "+value.ToString());
GetP().Enabled = value;
}
}
public UInt32 ForeColor {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getForeColor for proxy for "+ GetP().ToString());
return AxHost.GetOleColorFromColor(((Control)GetP()).ForeColor);
}
set {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in setForeColor for proxy for "+ GetP().ToString()+" "+
value.ToString(CultureInfo.InvariantCulture));
GetP().ForeColor = AxHost.GetColorFromOleColor(value);
}
}
public int Height {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getHeight for proxy for "+ GetP().ToString());
return Pixel2Twip(GetP().Height, false);
}
set {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in setHeight for proxy for "+ GetP().ToString()+" "+
Twip2Pixel(value,false).ToString(CultureInfo.InvariantCulture));
GetP().Height = Twip2Pixel(value, false);
}
}
public int Left {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getLeft for proxy for "+ GetP().ToString());
return Pixel2Twip(GetP().Left, true);
}
set {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in setLeft for proxy for "+ GetP().ToString()+" "+
Twip2Pixel(value, true).ToString(CultureInfo.InvariantCulture));
GetP().Left = Twip2Pixel(value, true);
}
}
public object Parent {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getParent for proxy for "+ GetP().ToString());
return GetC().GetProxyForControl(GetC().parent);
}
}
public short TabIndex {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getTabIndex for proxy for "+ GetP().ToString());
return (short)GetP().TabIndex;
}
set {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in setTabIndex for proxy for "+ GetP().ToString()+" "+
value.ToString(CultureInfo.InvariantCulture));
GetP().TabIndex = (int)value;
}
}
public bool TabStop {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getTabStop for proxy for "+ GetP().ToString());
return GetP().TabStop;
}
set {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in setTabStop for proxy for "+ GetP().ToString()+" "+value.ToString());
GetP().TabStop = value;
}
}
public int Top {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getTop for proxy for "+ GetP().ToString());
return Pixel2Twip(GetP().Top, false);
}
set {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in setTop for proxy for "+ GetP().ToString()+" "+
Twip2Pixel(value, false).ToString(CultureInfo.InvariantCulture));
GetP().Top = Twip2Pixel(value, false);
}
}
public bool Visible {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getVisible for proxy for "+ GetP().ToString());
return GetP().Visible;
}
set {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in setVisible for proxy for "+ GetP().ToString()+" "+value.ToString());
GetP().Visible = value;
}
}
public int Width {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getWidth for proxy for "+ GetP().ToString());
return Pixel2Twip(GetP().Width,true);
}
set {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in setWidth for proxy for "+ GetP().ToString()+" "+
Twip2Pixel(value, true).ToString(CultureInfo.InvariantCulture));
GetP().Width = Twip2Pixel(value, true);
}
}
public string Name {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getName for proxy for "+ GetP().ToString());
return GetC().GetNameForControl(GetP());
}
}
public IntPtr Hwnd {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getHwnd for proxy for "+ GetP().ToString());
return GetP().Handle;
}
}
public object Container {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getContainer for proxy for "+ GetP().ToString());
return GetC().GetProxyForContainer();
}
}
public string Text {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getText for proxy for "+ GetP().ToString());
return GetP().Text;
}
set {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in setText for proxy for "+ GetP().ToString());
GetP().Text = value;
}
}
public void Move(Object left, Object top, Object width, Object height) {
}
// IReflect methods:
MethodInfo IReflect.GetMethod(String name,BindingFlags bindingAttr,Binder binder, Type[] types,ParameterModifier[] modifiers) {
return null;
}
MethodInfo IReflect.GetMethod(String name,BindingFlags bindingAttr) {
return null;
}
MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr) {
return new MethodInfo[] {this.GetType().GetMethod("Move")};
}
FieldInfo IReflect.GetField(String name, BindingFlags bindingAttr) {
return null;
}
FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr) {
return new FieldInfo[0];
}
PropertyInfo IReflect.GetProperty(String name, BindingFlags bindingAttr) {
PropertyInfo prop = GetP().GetType().GetProperty(name, bindingAttr);
if (prop == null) {
prop = this.GetType().GetProperty(name, bindingAttr);
}
return prop;
}
PropertyInfo IReflect.GetProperty(String name, BindingFlags bindingAttr, Binder binder,Type returnType, Type[] types, ParameterModifier[] modifiers) {
PropertyInfo prop = GetP().GetType().GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
if (prop == null) {
prop = this.GetType().GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
}
return prop;
}
PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr) {
PropertyInfo[] extenderProps = this.GetType().GetProperties(bindingAttr);
PropertyInfo[] ctlProps = GetP().GetType().GetProperties(bindingAttr);
if (extenderProps == null) {
return ctlProps;
}
else if (ctlProps == null) {
return extenderProps;
}
else {
int iProp = 0;
PropertyInfo[] props = new PropertyInfo[extenderProps.Length + ctlProps.Length];
foreach(PropertyInfo prop in extenderProps) {
props[iProp++] = prop;
}
foreach(PropertyInfo prop in ctlProps) {
props[iProp++] = prop;
}
return props;
}
}
MemberInfo[] IReflect.GetMember(String name, BindingFlags bindingAttr) {
MemberInfo[] memb = GetP().GetType().GetMember(name, bindingAttr);
if (memb == null) {
memb = this.GetType().GetMember(name, bindingAttr);
}
return memb;
}
MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr) {
MemberInfo[] extenderMembs = this.GetType().GetMembers(bindingAttr);
MemberInfo[] ctlMembs = GetP().GetType().GetMembers(bindingAttr);
if (extenderMembs == null) {
return ctlMembs;
}
else if (ctlMembs == null) {
return extenderMembs;
}
else {
MemberInfo[] membs = new MemberInfo[extenderMembs.Length + ctlMembs.Length];
Array.Copy(extenderMembs, 0, membs, 0, extenderMembs.Length);
Array.Copy(ctlMembs, 0, membs, extenderMembs.Length, ctlMembs.Length);
return membs;
}
}
Object IReflect.InvokeMember(String name, BindingFlags invokeAttr, Binder binder,
Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters) {
try {
return this.GetType().InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
}
catch(MissingMethodException) {
return this.GetP().GetType().InvokeMember(name, invokeAttr, binder, GetP(), args, modifiers, culture, namedParameters);
}
}
Type IReflect.UnderlyingSystemType {
get {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "In UnderlyingSystemType");
return null;
}
}
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="StateConverter"]/*' />
/// <devdoc>
/// StateConverter is a class that can be used to convert
/// State from one data type to another. Access this
/// class through the TypeDescriptor.
/// </devdoc>
/// <internalonly/>
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name="FullTrust")]
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")]
public class StateConverter : TypeConverter {
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.StateConverter.CanConvertFrom"]/*' />
/// <devdoc>
/// <para>Gets a value indicating whether this converter can
/// convert an object in the given source type to the native type of the converter
/// using the context.</para>
/// </devdoc>
/// <internalonly/>
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) {
if (sourceType == typeof(byte[])) {
return true;
}
return base.CanConvertFrom(context, sourceType);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.StateConverter.CanConvertTo"]/*' />
/// <devdoc>
/// <para>Gets a value indicating whether this converter can
/// convert an object to the given destination type using the context.</para>
/// </devdoc>
/// <internalonly/>
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) {
if (destinationType == typeof(byte[])) {
return true;
}
return base.CanConvertTo(context, destinationType);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.StateConverter.ConvertFrom"]/*' />
/// <devdoc>
/// <para>Converts the given object to the converter's native type.</para>
/// </devdoc>
/// <internalonly/>
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
if (value is byte[]) {
MemoryStream ms = new MemoryStream((byte[])value);
return new State(ms);
}
return base.ConvertFrom(context, culture, value);
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.StateConverter.ConvertTo"]/*' />
/// <devdoc>
/// Converts the given object to another type. The most common types to convert
/// are to and from a string object. The default implementation will make a call
/// to ToString on the object if the object is valid and if the destination
/// type is string. If this cannot convert to the desitnation type, this will
/// throw a NotSupportedException.
/// </devdoc>
/// <internalonly/>
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {
if (destinationType == null) {
throw new ArgumentNullException("destinationType");
}
if (destinationType == typeof(byte[])) {
if (value != null) {
MemoryStream ms = new MemoryStream();
State state = (State)value;
state.Save(ms);
ms.Close();
return ms.ToArray();
}
else
return new byte[0];
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.State"]/*' />
/// <devdoc>
/// <para>The class which encapsulates the persisted state of the underlying activeX control
/// An instance of this class my be obtained either by calling getOcxState on an
/// AxHost object, or by reading in from a stream.</para>
/// </devdoc>
[
TypeConverterAttribute(typeof(TypeConverter)),
Serializable
]
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name="FullTrust")]
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")]
[SuppressMessage("Microsoft.Usage", "CA2240:ImplementISerializableCorrectly")]
public class State : ISerializable {
private int VERSION = 1;
private int length;
private byte[] buffer;
internal int type;
private MemoryStream ms;
private UnsafeNativeMethods.IStorage storage;
private UnsafeNativeMethods.ILockBytes iLockBytes;
private bool manualUpdate = false;
private string licenseKey = null;
private PropertyBagStream propBag;
// create on save from ipersist stream
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
internal State(MemoryStream ms, int storageType, AxHost ctl, PropertyBagStream propBag) {
type = storageType;
this.propBag = propBag;
// dangerous?
length = (int)ms.Length;
this.ms = ms;
this.manualUpdate = ctl.GetAxState(AxHost.manualUpdate);
this.licenseKey = ctl.GetLicenseKey();
}
internal State(PropertyBagStream propBag) {
this.propBag = propBag;
}
internal State(MemoryStream ms) {
this.ms = ms;
this.length = (int)ms.Length;
InitializeFromStream(ms);
}
// create on init new w/ storage...
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
internal State(AxHost ctl) {
CreateStorage();
manualUpdate = ctl.GetAxState(AxHost.manualUpdate);
licenseKey = ctl.GetLicenseKey();
type = STG_STORAGE;
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.State.State2"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public State(Stream ms, int storageType, bool manualUpdate, string licKey) {
type = storageType;
// dangerous?
length = (int)ms.Length;
this.manualUpdate = manualUpdate;
this.licenseKey = licKey;
InitializeBufferFromStream(ms);
}
/**
* Constructor used in deserialization
*/
protected State(SerializationInfo info, StreamingContext context) {
SerializationInfoEnumerator sie = info.GetEnumerator();
if (sie == null) {
return;
}
for (; sie.MoveNext();) {
if (String.Compare(sie.Name, "Data", true, CultureInfo.InvariantCulture) == 0) {
try {
byte[] dat = (byte[])sie.Value;
if (dat != null) {
InitializeFromStream(new MemoryStream(dat));
}
}
catch (Exception e) {
Debug.Fail("failure: " + e.ToString());
}
}
else if (String.Compare(sie.Name, "PropertyBagBinary", true, CultureInfo.InvariantCulture) == 0) {
try {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Loading up property bag from stream...");
byte[] dat = (byte[])sie.Value;
if (dat != null) {
this.propBag = new PropertyBagStream();
propBag.Read(new MemoryStream(dat));
}
}
catch (Exception e) {
Debug.Fail("failure: " + e.ToString());
}
}
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
internal int Type {
get {
return type;
}
set {
type = value;
}
}
internal bool _GetManualUpdate() {
return manualUpdate;
}
internal string _GetLicenseKey() {
return licenseKey;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
private void CreateStorage() {
Debug.Assert(storage == null, "but we already have a storage!!!");
IntPtr hglobal = IntPtr.Zero;
if (buffer != null) {
hglobal = UnsafeNativeMethods.GlobalAlloc(NativeMethods.GMEM_MOVEABLE, length);
IntPtr pointer = UnsafeNativeMethods.GlobalLock(new HandleRef(null, hglobal));
try {
if (pointer != IntPtr.Zero) {
Marshal.Copy(buffer, 0, pointer, length);
}
}
finally {
UnsafeNativeMethods.GlobalUnlock(new HandleRef(null, hglobal));
}
}
bool failed = false;
try {
iLockBytes = UnsafeNativeMethods.CreateILockBytesOnHGlobal(new HandleRef(null, hglobal), true);
if (buffer == null) {
storage = UnsafeNativeMethods.StgCreateDocfileOnILockBytes(iLockBytes,
NativeMethods.STGM_CREATE | NativeMethods.STGM_READWRITE | NativeMethods.STGM_SHARE_EXCLUSIVE, 0);
}
else {
storage = UnsafeNativeMethods.StgOpenStorageOnILockBytes(iLockBytes,
null, NativeMethods.STGM_READWRITE | NativeMethods.STGM_SHARE_EXCLUSIVE, 0, 0);
}
}
catch (Exception t) {
Debug.Fail(t.ToString());
failed = true;
}
if (failed) {
if (iLockBytes == null && hglobal != IntPtr.Zero) {
UnsafeNativeMethods.GlobalFree(new HandleRef(null, hglobal));
}
else {
iLockBytes = null;
}
storage = null;
}
}
internal UnsafeNativeMethods.IPropertyBag GetPropBag() {
return propBag;
}
internal UnsafeNativeMethods.IStorage GetStorage() {
if (storage == null)
CreateStorage();
return storage;
}
internal UnsafeNativeMethods.IStream GetStream() {
if (ms == null) {
Debug.Assert(buffer != null, "gotta have the buffer already...");
if (buffer == null) return null;
ms = new MemoryStream(buffer);
}
else {
ms.Seek(0, SeekOrigin.Begin);
}
return new UnsafeNativeMethods.ComStreamFromDataStream(ms);
}
private void InitializeFromStream(Stream ids) {
BinaryReader br = new BinaryReader(ids);
type = br.ReadInt32();
int version = br.ReadInt32();
manualUpdate = br.ReadBoolean();
int cc = br.ReadInt32();
if (cc != 0) {
licenseKey = new string(br.ReadChars(cc));
}
for (int skipUnits = br.ReadInt32(); skipUnits > 0; skipUnits --) {
int len = br.ReadInt32();
ids.Position = ids.Position + len;
}
length = br.ReadInt32();
if (length > 0)
buffer = br.ReadBytes(length);
}
private void InitializeBufferFromStream(Stream ids) {
BinaryReader br = new BinaryReader(ids);
length = br.ReadInt32();
if (length > 0)
buffer = br.ReadBytes(length);
}
internal State RefreshStorage(UnsafeNativeMethods.IPersistStorage iPersistStorage) {
Debug.Assert(storage != null, "how can we not have a storage object?");
Debug.Assert(iLockBytes != null, "how can we have a storage w/o ILockBytes?");
if (storage == null || iLockBytes == null) return null;
iPersistStorage.Save(storage, true);
storage.Commit(0);
iPersistStorage.HandsOffStorage();
try {
buffer = null;
ms = null;
NativeMethods.STATSTG stat = new NativeMethods.STATSTG();
iLockBytes.Stat(stat, NativeMethods.Ole.STATFLAG_NONAME);
length = (int) stat.cbSize;
buffer = new byte[length];
IntPtr hglobal = UnsafeNativeMethods.GetHGlobalFromILockBytes(iLockBytes);
IntPtr pointer = UnsafeNativeMethods.GlobalLock(new HandleRef(null, hglobal));
try {
if (pointer != IntPtr.Zero) {
Marshal.Copy(pointer, buffer, 0, length);
}
else {
length = 0;
buffer = null;
}
}
finally {
UnsafeNativeMethods.GlobalUnlock(new HandleRef(null, hglobal));
}
}
finally {
iPersistStorage.SaveCompleted(storage);
}
return this;
}
internal void Save(MemoryStream stream) {
BinaryWriter bw = new BinaryWriter(stream);
bw.Write(type);
bw.Write(VERSION);
bw.Write(manualUpdate);
if (licenseKey != null) {
bw.Write(licenseKey.Length);
bw.Write(licenseKey.ToCharArray());
}
else {
bw.Write((int)0);
}
bw.Write((int)0); // skip units
bw.Write(length);
if (buffer != null) {
bw.Write(buffer);
}
else if (ms != null) {
ms.Position = 0;
ms.WriteTo(stream);
}
else {
Debug.Assert(length == 0, "if we have no data, then our length has to be 0");
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="State.ISerializable.GetObjectData"]/*' />
/// <devdoc>
/// ISerializable private implementation
/// </devdoc>
/// <internalonly/>
void ISerializable.GetObjectData(SerializationInfo si, StreamingContext context) {
IntSecurity.UnmanagedCode.Demand();
MemoryStream stream = new MemoryStream();
Save(stream);
si.AddValue("Data", stream.ToArray());
if (propBag != null) {
try {
stream = new MemoryStream();
propBag.Write(stream);
si.AddValue("PropertyBagBinary", stream.ToArray());
}
catch (Exception e) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Failed to serialize the property bag into ResX : " + e.ToString());
}
}
}
}
internal class PropertyBagStream : UnsafeNativeMethods.IPropertyBag {
private Hashtable bag = new Hashtable();
internal void Read(Stream stream) {
BinaryFormatter formatter = new BinaryFormatter();
try {
bag = (Hashtable)formatter.Deserialize(stream);
}
catch {
// Error reading. Just init an empty hashtable.
bag = new Hashtable();
}
}
int UnsafeNativeMethods.IPropertyBag.Read(string pszPropName, ref object pVar, UnsafeNativeMethods.IErrorLog pErrorLog) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Reading property " + pszPropName + " from OCXState propertybag.");
if (!bag.Contains(pszPropName))
return NativeMethods.E_INVALIDARG;
pVar = bag[pszPropName];
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "\tValue=" + ((pVar == null) ? "<null>" : pVar.ToString()));
// The EE returns a VT_EMPTY for a null. The problem is that visual basic6 expects the caller to respect the
// "hint" it gives in the VariantType. For eg., for a VT_BSTR, it expects that the callee will null
// out the BSTR field of the variant. Since, the EE or us cannot do anything about this, we will return
// a E_INVALIDARG rather than let visual basic6 crash.
//
return (pVar == null) ? NativeMethods.E_INVALIDARG : NativeMethods.S_OK;
}
int UnsafeNativeMethods.IPropertyBag.Write(string pszPropName, ref object pVar) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "Writing property " + pszPropName + " [" + pVar + "] into OCXState propertybag.");
if (pVar != null && !pVar.GetType().IsSerializable) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "\t " + pVar.GetType().FullName + " is not serializable.");
return NativeMethods.S_OK;
}
bag[pszPropName] = pVar;
return NativeMethods.S_OK;
}
internal void Write(Stream stream) {
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, bag);
}
}
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AboutBoxDelegate"]/*' />
protected delegate void AboutBoxDelegate();
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxComponentEditor"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name="FullTrust")]
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")]
[ComVisible(false)]
public class AxComponentEditor : WindowsFormsComponentEditor {
/// <include file='doc\AxHost.uex' path='docs/doc[@for="AxHost.AxComponentEditor.EditComponent"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public override bool EditComponent(ITypeDescriptorContext context, object obj, IWin32Window parent) {
AxHost host = obj as AxHost;
if (host != null)
{
try {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in AxComponentEditor.EditComponent");
((UnsafeNativeMethods.IOleControlSite)host.oleSite).ShowPropertyFrame();
return true;
}
catch (Exception t) {
Debug.Fail(t.ToString());
throw;
}
}
return false;
}
}
/// <devdoc>
/// </devdoc>
internal class AxPropertyDescriptor : PropertyDescriptor {
private PropertyDescriptor baseProp;
internal AxHost owner;
private DispIdAttribute dispid;
private TypeConverter converter;
private UITypeEditor editor;
private ArrayList updateAttrs = new ArrayList();
private int flags = 0;
private const int FlagUpdatedEditorAndConverter = 0x00000001;
private const int FlagCheckGetter = 0x00000002;
private const int FlagGettterThrew = 0x00000004;
private const int FlagIgnoreCanAccessProperties = 0x00000008;
private const int FlagSettingValue = 0x00000010;
[
SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors") // Shipped in Everett
]
internal AxPropertyDescriptor(PropertyDescriptor baseProp, AxHost owner) : base(baseProp) {
this.baseProp = baseProp;
this.owner = owner;
// Get the category for this dispid.
//
dispid = (DispIdAttribute)baseProp.Attributes[typeof(DispIdAttribute)];
if (dispid != null) {
// Look to see if this property has a property page.
// If it does, then it needs to be Browsable(true).
//
if (!this.IsBrowsable && !this.IsReadOnly) {
Guid g = GetPropertyPage(dispid.Value);
if (!Guid.Empty.Equals(g)) {
Debug.WriteLineIf(AxPropTraceSwitch.TraceVerbose, "Making property: " + this.Name + " browsable because we found an property page.");
AddAttribute(new BrowsableAttribute(true));
}
}
// Use the CategoryAttribute provided by the OCX.
//
CategoryAttribute cat = owner.GetCategoryForDispid(dispid.Value);
if (cat != null) {
AddAttribute(cat);
}
// Check to see if this a DataSource property.
// If it is, we can always get and set the value of this property.
//
if (this.PropertyType.GUID.Equals(dataSource_Guid)) {
SetFlag(FlagIgnoreCanAccessProperties, true);
}
}
}
public override Type ComponentType {
get {
return baseProp.ComponentType;
}
}
public override TypeConverter Converter {
get {
if (dispid != null) {
UpdateTypeConverterAndTypeEditorInternal(false, Dispid);
}
return (converter != null) ? converter : base.Converter;
}
}
internal int Dispid {
get {
DispIdAttribute dispid = (DispIdAttribute)baseProp.Attributes[typeof(DispIdAttribute)];
if (dispid != null) {
return dispid.Value;
}
return NativeMethods.ActiveX.DISPID_UNKNOWN;
}
}
public override bool IsReadOnly {
get {
return baseProp.IsReadOnly;
}
}
public override Type PropertyType {
get {
return baseProp.PropertyType;
}
}
internal bool SettingValue {
get {
return GetFlag(FlagSettingValue);
}
}
private void AddAttribute(Attribute attr) {
updateAttrs.Add(attr);
}
public override bool CanResetValue(object o) {
return baseProp.CanResetValue(o);
}
public override object GetEditor(Type editorBaseType) {
UpdateTypeConverterAndTypeEditorInternal(false, dispid.Value);
if (editorBaseType.Equals(typeof(UITypeEditor)) && editor != null) {
return editor;
}
return base.GetEditor(editorBaseType);
}
private bool GetFlag(int flagValue) {
return ((flags & flagValue) == flagValue);
}
private Guid GetPropertyPage(int dispid) {
try {
NativeMethods.IPerPropertyBrowsing ippb = owner.GetPerPropertyBrowsing();
if (ippb == null) return Guid.Empty;
Guid rval;
if (NativeMethods.Succeeded(ippb.MapPropertyToPage(dispid, out rval))) {
return rval;
}
}
catch (COMException) {
}
catch (Exception t) {
Debug.Fail(t.ToString());
}
return Guid.Empty;
}
public override object GetValue(object component) {
if ((!GetFlag(FlagIgnoreCanAccessProperties) && !owner.CanAccessProperties) || GetFlag(FlagGettterThrew)) {
return null;
}
try {
// Some controls fire OnChanged() notifications when getting values of some properties. ASURT 20190.
// To prevent this kind of recursion, we check to see if we are already inside a OnChanged() call.
//
owner.NoComponentChangeEvents++;
return baseProp.GetValue(component);
}
catch (Exception e) {
if (!GetFlag(FlagCheckGetter)) {
Debug.WriteLineIf(AxPropTraceSwitch.TraceVerbose, "Get failed for : " + Name + " with exception: " + e.Message + " .Making property non-browsable.");
SetFlag(FlagCheckGetter, true);
AddAttribute(new BrowsableAttribute(false));
owner.RefreshAllProperties = true;
SetFlag(FlagGettterThrew, true);
}
throw e;
}
finally {
owner.NoComponentChangeEvents--;
}
}
public void OnValueChanged(object component) {
this.OnValueChanged(component, EventArgs.Empty);
}
public override void ResetValue(object o) {
baseProp.ResetValue(o);
}
private void SetFlag(int flagValue, bool value) {
if (value) {
flags |= flagValue;
}
else {
flags &= ~flagValue;
}
}
public override void SetValue(Object component, Object value) {
if (!GetFlag(FlagIgnoreCanAccessProperties) && !owner.CanAccessProperties) {
return;
}
// State oldOcxState = owner.OcxState;
try {
SetFlag(FlagSettingValue, true);
if (this.PropertyType.IsEnum && (value.GetType() != this.PropertyType)) {
baseProp.SetValue(component, Enum.ToObject(this.PropertyType, value));
}
else {
baseProp.SetValue(component, value);
}
}
finally {
SetFlag(FlagSettingValue, false);
}
OnValueChanged(component);
if (owner == component) {
owner.SetAxState(AxHost.valueChanged, true);
}
}
public override bool ShouldSerializeValue(object o) {
return baseProp.ShouldSerializeValue(o);
}
internal void UpdateAttributes() {
if (updateAttrs.Count == 0)
return;
ArrayList attributes = new ArrayList(AttributeArray);
foreach(Attribute attr in updateAttrs) {
attributes.Add(attr);
}
Attribute[] temp = new Attribute[attributes.Count];
attributes.CopyTo(temp, 0);
AttributeArray = temp;
updateAttrs.Clear();
}
/// <devdoc>
/// Called externally to update the editor or type converter.
/// This simply sets flags so this will happen, it doesn't actually to the update...
/// we wait and do that on-demand for perf.
/// </devdoc>
internal void UpdateTypeConverterAndTypeEditor(bool force) {
// if this is an external request, flip the flag to false so we do the update on demand.
//
if (GetFlag(FlagUpdatedEditorAndConverter) && force) {
SetFlag(FlagUpdatedEditorAndConverter, false);
}
}
/// <devdoc>
/// Called externally to update the editor or type converter.
/// This simply sets flags so this will happen, it doesn't actually to the update...
/// we wait and do that on-demand for perf.
/// </devdoc>
internal void UpdateTypeConverterAndTypeEditorInternal(bool force, int dispid) {
// check to see if we're being forced here or if the work really
// needs to be done.
//
if (GetFlag(FlagUpdatedEditorAndConverter) && !force) {
return;
}
if (owner.GetOcx() == null) {
return;
}
try {
NativeMethods.IPerPropertyBrowsing ppb = owner.GetPerPropertyBrowsing();
if (ppb != null) {
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(dispid, caStrings, caCookies);
}
catch(ExternalException ex) {
hr = ex.ErrorCode;
Debug.Fail("An exception occurred inside IPerPropertyBrowsing::GetPredefinedStrings(dispid=" +
dispid + "), object type=" + new ComNativeDescriptor().GetClassName(ppb));
}
if (hr != NativeMethods.S_OK) {
hasStrings = false;
// Destroy the existing editor if we created the current one
// so if the items have disappeared, we don't hold onto the old
// items.
if (converter is Com2EnumConverter) {
converter = null;
}
}
else {
hasStrings = true;
}
if (hasStrings) {
OleStrCAMarshaler stringMarshaler = new OleStrCAMarshaler(caStrings);
Int32CAMarshaler intMarshaler = new Int32CAMarshaler(caCookies);
if (stringMarshaler.Count > 0 && intMarshaler.Count > 0) {
if (converter == null) {
converter = new AxEnumConverter(this, new AxPerPropertyBrowsingEnum(this, owner, stringMarshaler, intMarshaler, true));
}
else if (converter is AxEnumConverter){
((AxEnumConverter)converter).RefreshValues();
AxPerPropertyBrowsingEnum axEnum = ((AxEnumConverter)converter).com2Enum as AxPerPropertyBrowsingEnum;
if (axEnum != null) {
axEnum.RefreshArrays(stringMarshaler, intMarshaler);
}
}
}
else {
//hasStrings = false;
}
}
else {
// if we didn't get any strings, try the proppage edtior
//
// Check to see if this is a property that we have already massaged to be a
// .Net type. If it is, don't bother with custom property pages. We already
// have a .Net Editor for this type.
//
ComAliasNameAttribute comAlias = (ComAliasNameAttribute)baseProp.Attributes[typeof(ComAliasNameAttribute)];
if (comAlias == null) {
Guid g = GetPropertyPage(dispid);
if (!Guid.Empty.Equals(g)) {
editor = new AxPropertyTypeEditor(this, g);
// Show any non-browsable property that has an editor through a
// property page.
//
if (!this.IsBrowsable) {
Debug.WriteLineIf(AxPropTraceSwitch.TraceVerbose, "Making property: " + this.Name + " browsable because we found an editor.");
AddAttribute(new BrowsableAttribute(true));
}
}
}
}
}
SetFlag(FlagUpdatedEditorAndConverter, true);
}
catch (Exception e) {
Debug.WriteLineIf(AxPropTraceSwitch.TraceVerbose, "could not get the type editor for property: " + this.Name + " Exception: " + e);
}
}
}
private class AxPropertyTypeEditor : UITypeEditor {
private AxPropertyDescriptor propDesc;
private Guid guid;
public AxPropertyTypeEditor(AxPropertyDescriptor pd, Guid guid) {
propDesc = pd;
this.guid = guid;
}
/// <include file='doc\AxPropertyTypeEditor.uex' path='docs/doc[@for="AxPropertyTypeEditor.EditValue"]/*' />
/// <devdoc>
/// Takes the value returned from valueAccess.getValue() and modifies or replaces
/// the value, passing the result into valueAccess.setValue(). This is where
/// an editor can launch a modal dialog or create a drop down editor to allow
/// the user to modify the value. Host assistance in presenting UI to the user
/// can be found through the valueAccess.getService function.
/// </devdoc>
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) {
try {
object instance = context.Instance;
propDesc.owner.ShowPropertyPageForDispid(propDesc.Dispid, this.guid);
}
catch (Exception ex1) {
if (provider != null) {
IUIService uiSvc = (IUIService)provider.GetService(typeof(IUIService));
if (uiSvc != null){
uiSvc.ShowError(ex1, SR.GetString(SR.ErrorTypeConverterFailed));
}
}
}
return value;
}
/// <devdoc>
/// Retrieves the editing style of the Edit method. If the method
/// is not supported, this will return None.
/// </devdoc>
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) {
return UITypeEditorEditStyle.Modal;
}
}
/// <devdoc>
/// simple derivation of the com2enumconverter that allows us to intercept
/// the call to GetStandardValues so we can on-demand update the enum values.
/// </devdoc>
private class AxEnumConverter : Com2EnumConverter {
private AxPropertyDescriptor target;
public AxEnumConverter(AxPropertyDescriptor target, Com2Enum com2Enum) : base(com2Enum) {
this.target = target;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) {
// make sure the converter has been properly refreshed -- calling
// the Converter property does this.
//
TypeConverter tc = this;
tc = target.Converter;
return base.GetStandardValues(context);
}
}
// This exists for perf reasons. We delay doing this until we
// are actually asked for the array of values.
//
private class AxPerPropertyBrowsingEnum : Com2Enum {
private AxPropertyDescriptor target;
private AxHost owner;
private OleStrCAMarshaler nameMarshaller;
private Int32CAMarshaler valueMarshaller;
private bool arraysFetched;
public AxPerPropertyBrowsingEnum(AxPropertyDescriptor targetObject, AxHost owner, OleStrCAMarshaler names, Int32CAMarshaler values, bool allowUnknowns) : base(new string[0], new object[0], allowUnknowns) {
this.target = targetObject;
this.nameMarshaller = names;
this.valueMarshaller = values;
this.owner = owner;
this.arraysFetched = false;
}
/// <include file='doc\AxPerPropertyBrowsingEnum.uex' path='docs/doc[@for="AxHost.AxPerPropertyBrowsingEnum.Values"]/*' />
/// <devdoc>
/// Retrieve a copy of the value array
/// </devdoc>
public override object[] Values {
get {
EnsureArrays();
return base.Values;
}
}
/// <devdoc>
/// Retrieve a copy of the nme array.
/// </devdoc>
public override string[] Names {
get {
EnsureArrays();
return base.Names;
}
}
// 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)owner.GetPerPropertyBrowsing();
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.
//
for (int i = 0; i < nameItems.Length; 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();
}
var.Clear();
itemCount++;
}
// pass this data down to the base Com2Enum object...
if (itemCount > 0) {
string[] strings = new string[itemCount];
Array.Copy(nameItems, 0, strings, 0, itemCount);
base.PopulateArrays(strings, valueItems);
}
}
}
catch (Exception ex) {
Debug.Fail("Failed to build IPerPropertyBrowsing editor. " + ex.GetType().Name + ", " + ex.Message);
}
}
internal void RefreshArrays( OleStrCAMarshaler names, Int32CAMarshaler values) {
this.nameMarshaller = names;
this.valueMarshaller = values;
this.arraysFetched = false;
}
#if false
// FxCop: Currently not used
private string GetDisplayString(int dispid, ref bool success) {
NativeMethods.IPerPropertyBrowsing ppb = (NativeMethods.IPerPropertyBrowsing)owner.GetPerPropertyBrowsing();
string[] strVal = new string[1];
int hr = ppb.GetDisplayString(dispid, strVal);
if (hr == NativeMethods.S_OK) {
success = (strVal[0] != null);
//Debug.Assert(success, "IPerPropertyBrowsing::GetDisplayString returned NULL and S_OK -- this is not a valid state. This component does not property implement IPerPropertyBrowsing. (component class=" + TypeDescriptor.GetClassName(ppb) + ")");
return strVal[0];
}
else {
success = false;
}
return null;
}
#endif
protected override void PopulateArrays(string[] names, object[] values) {
// we call base.PopulateArrays directly when we actually want to do this.
}
public override object FromString(string s) {
EnsureArrays();
return base.FromString(s);
}
public override string ToString(object v) {
EnsureArrays();
return base.ToString(v);
}
}
}
}
|