DocumentDesigner.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / Designer / WinForms / System / WinForms / Design / DocumentDesigner.cs / 2 / DocumentDesigner.cs

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

/* 
 */ 
namespace System.Windows.Forms.Design {
    using System.Design; 
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Formatters;
    using Microsoft.Win32;
    using System.Runtime.InteropServices; 
    using System.ComponentModel;
    using System.Diagnostics; 
    using System; 
    using System.IO;
    using System.Text; 
    using System.Collections;
    using System.ComponentModel.Design;
    using System.ComponentModel.Design.Serialization;
    using System.Drawing; 
    using System.Drawing.Design;
    using System.Reflection; 
    using System.Windows.Forms; 
    using System.Windows.Forms.Design.Behavior;
    using System.Globalization; 
    using System.Runtime.InteropServices.ComTypes;
    using TYPELIBATTR = System.Runtime.InteropServices.ComTypes.TYPELIBATTR;
    using IDataObject = System.Windows.Forms.IDataObject;
 
    /// 
    ///  
    ///    Provides a designer that extends the ScrollableControlDesigner and implements 
    ///       IRootDesigner.
    ///  
    [
    ToolboxItemFilter("System.Windows.Forms")
    ]
    public class DocumentDesigner : ScrollableControlDesigner, IRootDesigner, IToolboxUser, IOleDragClient { 

        private DesignerFrame                  frame; 
        private ControlCommandSet              commandSet; 
        private InheritanceService             inheritanceService;
        private EventHandlerService            eventHandlerService; 
        private DesignBindingValueUIHandler    designBindingValueUIHandler;
        private BehaviorService                behaviorService;
        private SelectionManager               selectionManager;
        private DesignerExtenders              designerExtenders; 
        private InheritanceUI                  inheritanceUI;
        private PbrsForward                    pbrsFwd; 
        private ArrayList                      suspendedComponents = null; 
        private UndoEngine                     undoEngine = null;
        private bool                           initializing;   // is the designer initializing? 

        //used to keep the state of the tab order view
        //
        private bool queriedTabOrder = false; 
        private MenuCommand tabOrderCommand = null;
 
        //our menu editor service 
        //
        ///  
        protected IMenuEditorService    menuEditorService = null;


        // The component tray 
        //
        private ComponentTray componentTray; 
 
        private int trayHeight = 80;
        private bool trayLargeIcon = false; 
        private bool trayAutoArrange = false;
        private bool trayLayoutSuspended = false;

        // ActiveX support 
        //
        private static Guid htmlDesignTime = new Guid("73CEF3DD-AE85-11CF-A406-00AA00C00940"); 
 
        private Hashtable axTools = null;
        private static TraceSwitch AxToolSwitch     = new TraceSwitch("AxTool", "ActiveX Toolbox Tracing"); 
        private static readonly string axClipFormat = "CLSID";
        private ToolboxItemCreatorCallback toolboxCreator = null;

 

        ///  
        ///     Property shadow for ContainerControl's AutoScaleDimenions.  We shadow here so it 
        ///     always returns the CurrentAutoScaleDimensions for the control. This way the control's
        ///     state always adapts to the current font / monitor. 
        /// 
        private SizeF AutoScaleDimensions {
            get {
                ContainerControl c = Control as ContainerControl; 
                if (c != null) {
                    return c.CurrentAutoScaleDimensions; 
                } 
                Debug.Fail("AutoScaleDimensions should not be shadowed on non-ContainerControl objects.");
                return SizeF.Empty; 
            }
            set {
                ContainerControl c = Control as ContainerControl;
                if (c != null) { 
                    c.AutoScaleDimensions = value;
                } 
            } 
        }
 
        /// 
        ///     Property shadow for ContainerControl's AutoScaleMode.  We shadow here so it
        ///     never gets to the control; it can be very distracting if you change the font
        ///     and have the form you're designing suddenly move on you. 
        /// 
        private AutoScaleMode AutoScaleMode { 
            get { 
                ContainerControl c = Control as ContainerControl;
                if (c != null) { 
                    return c.AutoScaleMode;
                }
                Debug.Fail("AutoScaleMode should not be shadowed on non-ContainerControl objects.");
                return AutoScaleMode.Inherit; 
            }
            set { 
                ShadowProperties["AutoScaleMode"] = value; 
                ContainerControl c = Control as ContainerControl;
                if (c != null && c.AutoScaleMode != value) { 
                    c.AutoScaleMode = value;

                    // If we're not loading and this changes update
                    // the current auto scale dimensions. 
                    IDesignerHost host = GetService(typeof(IDesignerHost)) as IDesignerHost;
                    if (host != null && !host.Loading) { 
                        c.AutoScaleDimensions = c.CurrentAutoScaleDimensions; 
                    }
                } 
            }
        }

        ///  
        ///     BackColor property on control.  We shadow this property at design time.
        ///  
        private Color BackColor { 
            get {
                return Control.BackColor; 
            }
            set {
                ShadowProperties["BackColor"] = value;
                if (value.IsEmpty) { 
                    value = SystemColors.Control;
                } 
                Control.BackColor = value; 
            }
        } 

        /// 
        ///     Location property on control.  We shadow this property at design time.
        ///  
        [DefaultValue(typeof(Point), "0, 0")]
        private Point Location { 
            get { 
                return (Point)ShadowProperties["Location"];
            } 
            set {
                ShadowProperties["Location"] = value;
            }
        } 

        ///  
        ///  
        ///     We override our selectino rules to make the document non-sizeable.
        ///  
        public override SelectionRules SelectionRules {
            get {
                SelectionRules rules = base.SelectionRules;
                rules &= ~(SelectionRules.Moveable | SelectionRules.TopSizeable | SelectionRules.LeftSizeable); 

                return rules; 
            } 
        }
 
        /// 
        ///      Determines if the tab order UI is active.  When tab order is active, we don't want to forward
        ///      any WndProc messages to the menu editor service (those are all non-selectable components)
        ///  
        private bool TabOrderActive {
            get { 
                if (!queriedTabOrder) { 
                    queriedTabOrder = true;
                    IMenuCommandService menuCommandService = (IMenuCommandService)GetService(typeof(IMenuCommandService)); 
                    if (menuCommandService != null)
                        tabOrderCommand = menuCommandService.FindCommand(MenuCommands.TabOrder);
                }
 
                if (tabOrderCommand != null) {
                    return tabOrderCommand.Checked; 
                } 

                return false; 
            }
        }

        ///  
        /// 
        [DefaultValue(true)] 
        private bool TrayAutoArrange { 
            get {
                return trayAutoArrange; 
            }

            set {
                trayAutoArrange = value; 
                if (componentTray != null) {
                    componentTray.AutoArrange = trayAutoArrange; 
                } 
            }
        } 

        /// 
        /// 
        [DefaultValue(false)] 
        private bool TrayLargeIcon {
            get { 
                return trayLargeIcon; 
            }
 
            set {
                trayLargeIcon = value;
                if (componentTray != null) {
                    componentTray.ShowLargeIcons = trayLargeIcon; 
                }
            } 
        } 

        ///  
        /// 
        [DefaultValue(80)]
        private int TrayHeight {
            get { 
                if (componentTray != null) {
                    return componentTray.Height; 
                } 
                else {
                    return trayHeight; 
                }
            }

            set { 
                trayHeight = value;
                if (componentTray != null) { 
                    componentTray.Height = trayHeight; 
                }
            } 
        }

        /// 
        ///  
        /// 
        /// Retrieves the control view instance for the given component. 
        /// For Win32 designer, this will often be the component itself. 
        /// 
        Control IOleDragClient.GetControlForComponent(object component) { 
            Control c = GetControl(component);
            if (c != null)
                return c;
 
            if (componentTray != null) {
                return ((IOleDragClient)componentTray).GetControlForComponent(component); 
            } 

            return null; 
        }

        internal virtual bool CanDropComponents(DragEventArgs de) {
            // If there is no tray we bail. 
            if (componentTray == null)
                return true; 
 
            // Figure out if any of the components in the drag-drop are children
            // of our own tray. If so, we should prevent this drag-drop from proceeding. 
            //
            OleDragDropHandler ddh = GetOleDragHandler();
            object[] dragComps = ddh.GetDraggingObjects(de);
 
            if (dragComps != null) {
                IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); 
                for (int  i = 0; i < dragComps.Length; i++) { 
                    IComponent comp = dragComps[i] as IComponent;
                    if (host == null || dragComps[i] == null || comp == null) { 
                        continue;
                    }

                    if (componentTray.IsTrayComponent(comp)) { 
                        return false;
                    } 
                } 
            }
 
            //ToolStripItems cannot be dropped on any ParentControlDesigners since they have custom DataObject Format.
            if (de.Data is ToolStripItemDataObject)
            {
               return false; 
            }
 
            return true; 
        }
 
        private ToolboxItem CreateAxToolboxItem(IDataObject dataObject) {
            AxToolboxItem tool = null;

            // Read the stream out of the dataobject and get hold of the CLSID of the Toolbox item. 
            //
            MemoryStream stm = (MemoryStream)dataObject.GetData(axClipFormat, true); 
            int len = (int)stm.Length; 
            byte[] bytes = new byte[len];
            stm.Read(bytes, 0, len); 

            string clsid = System.Text.Encoding.Default.GetString(bytes);
            int index = clsid.IndexOf("}");
            clsid = clsid.Substring(0, index+1); 
            Debug.WriteLineIf(AxToolSwitch.TraceVerbose, "\tCLSID of the Toolbox item: " + clsid);
 
            // Look to see if we can find the Control key for this CLSID. If present, create a 
            // new AxToolboxItem and add it to the cache.
            // 
            if (IsSupportedActiveXControl(clsid)) {
                // Look to see if we have already cached the ToolboxItem.
                //
                if (axTools != null) { 
                    tool = (AxToolboxItem)axTools[clsid];
                    if (tool != null) { 
                        if (AxToolSwitch.TraceVerbose) Debug.WriteLine("Found AxToolboxItem in tool cache"); 
                        return tool;
                    } 
                }

                tool = new AxToolboxItem(clsid);
                if (axTools == null) { 
                    axTools = new Hashtable();
                } 
                axTools.Add(clsid, tool); 
                Debug.WriteLineIf(AxToolSwitch.TraceVerbose, "\tAdded AxToolboxItem");
                return tool; 
            }
            else {
                return null;
            } 
        }
 
        private ToolboxItem CreateCfCodeToolboxItem(IDataObject dataObject) { 

            object serializationData = null; 

            serializationData = dataObject.GetData(OleDragDropHandler.NestedToolboxItemFormat, false);
            if (serializationData != null) {
                return (ToolboxItem)serializationData; 
            }
 
            serializationData = dataObject.GetData(OleDragDropHandler.DataFormat, false); 
            if (serializationData != null) {    //backcompat
                return new OleDragDropHandler.CfCodeToolboxItem(serializationData); ; 
            }

            return null;
        } 

        ///  
        ///  
        ///     Disposes of this designer.
        ///  
        protected override void Dispose(bool disposing) {
            if (disposing) {
                IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
                Debug.Assert(host != null, "Must have a designer host on dispose"); 

                if (host != null) { 
 
                    //Remove Adorner Window which hosts DropDowns.
                    ToolStripAdornerWindowService toolWindow = (ToolStripAdornerWindowService)GetService(typeof(ToolStripAdornerWindowService)); 
                    if (toolWindow != null)
                    {
                        toolWindow.Dispose();
                        host.RemoveService(typeof(ToolStripAdornerWindowService)); 
                    }
 
                    host.Activated -= new EventHandler(OnDesignerActivate); 
                    host.Deactivated -= new EventHandler(OnDesignerDeactivate);
 
                    // If the tray wasn't destroyed, then we got some sort of inbalance
                    // in our add/remove calls.  Don't sweat it, but do remove the tray.
                    //
                    if (componentTray != null) { 
                        ISplitWindowService sws = (ISplitWindowService)GetService(typeof(ISplitWindowService));
                        if (sws != null) { 
                            sws.RemoveSplitWindow(componentTray); 
                            componentTray.Dispose();
                            componentTray = null; 
                        }

                        host.RemoveService(typeof(ComponentTray));
                    } 

                    IComponentChangeService cs = (IComponentChangeService)GetService(typeof(IComponentChangeService)); 
                    if (cs != null) { 
                        cs.ComponentAdded -= new ComponentEventHandler(this.OnComponentAdded);
                        cs.ComponentChanged -= new ComponentChangedEventHandler(this.OnComponentChanged); 
                        cs.ComponentRemoved -= new ComponentEventHandler(this.OnComponentRemoved);
                    }

                    if (undoEngine != null) { 
                        undoEngine.Undoing -= new EventHandler(this.OnUndoing);
                        undoEngine.Undone -= new EventHandler(this.OnUndone); 
                    } 

                    if (toolboxCreator != null) { 
                        IToolboxService toolbox = (IToolboxService)GetService(typeof(IToolboxService));
                        Debug.Assert(toolbox != null, "No toolbox service available");
                        if (toolbox != null) {
                            Debug.WriteLineIf(AxToolSwitch.TraceVerbose, "Removing DocumentDesigner as CLSID ToolboxItemCreator"); 
                            toolbox.RemoveCreator(axClipFormat, host);
 
                            Debug.WriteLineIf(AxToolSwitch.TraceVerbose, "Removing DocumentDesigner as CF_CODE ToolboxItemCreator"); 
                            toolbox.RemoveCreator(OleDragDropHandler.DataFormat, host);
 
                            Debug.WriteLineIf(AxToolSwitch.TraceVerbose, "Removing DocumentDesigner as CF_TOOLBOXITEM ToolboxItemCreator");
                            toolbox.RemoveCreator(OleDragDropHandler.NestedToolboxItemFormat, host);

                        } 
                        toolboxCreator = null;
                    } 
                } 

                ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService)); 
                if (ss != null) {
                    ss.SelectionChanged -= new EventHandler(this.OnSelectionChanged);
                }
 
                if (behaviorService != null) {
                    behaviorService.Dispose(); 
                    behaviorService = null; 
                }
 
                if (selectionManager != null) {
                    selectionManager.Dispose();
                    selectionManager = null;
                } 

                if (componentTray != null) { 
                    if (host != null) { 
                        ISplitWindowService sws = (ISplitWindowService)GetService(typeof(ISplitWindowService));
                        if (sws != null) { 
                            sws.RemoveSplitWindow(componentTray);
                        }
                    }
                    componentTray.Dispose(); 
                    componentTray = null;
                } 
 
                if (this.pbrsFwd != null) {
                    this.pbrsFwd.Dispose(); 
                    this.pbrsFwd = null;
                }

                if (frame != null) { 
                    frame.Dispose();
                    frame = null; 
                } 

                if (commandSet != null) { 
                    commandSet.Dispose();
                    commandSet = null;
                }
 
                if (inheritanceService != null) {
                    inheritanceService.Dispose(); 
                    inheritanceService = null; 
                }
 
                if (inheritanceUI != null) {
                    inheritanceUI.Dispose();
                    inheritanceUI = null;
                } 

                if (designBindingValueUIHandler != null) { 
 
                    IPropertyValueUIService pvUISvc = (IPropertyValueUIService)GetService(typeof(IPropertyValueUIService));
                    if (pvUISvc != null) { 
                        pvUISvc.RemovePropertyValueUIHandler(new PropertyValueUIHandler(designBindingValueUIHandler.OnGetUIValueItem));
                        pvUISvc = null;
                    }
 
                    designBindingValueUIHandler.Dispose();
                    designBindingValueUIHandler = null; 
                } 

                if (designerExtenders != null) { 
                    designerExtenders.Dispose();
                    designerExtenders = null;
                }
 
                if (axTools != null) {
                    axTools.Clear(); 
                } 

 
                if (host != null) {
                    host.RemoveService(typeof(BehaviorService));
                    host.RemoveService(typeof(ToolStripAdornerWindowService));
                    host.RemoveService(typeof(SelectionManager)); 
                    host.RemoveService(typeof(IInheritanceService));
                    host.RemoveService(typeof(IEventHandlerService)); 
                    host.RemoveService(typeof(IOverlayService)); 
                    host.RemoveService(typeof(ISplitWindowService));
                    host.RemoveService(typeof(InheritanceUI)); 
                }
            }

            base.Dispose(disposing); 
        }
 
        ///  
        /// 
        ///     Returns an array of Glyph objects representing the selection 
        ///     borders and grab handles for the related Component.  Note that
        ///     based on 'selType' the Glyphs returned will either: represent
        ///     a fully resizeable selection border with grab handles, a locked
        ///     selection border, or a single 'hidden' selection Glyph. 
        /// 
        public override GlyphCollection GetGlyphs(GlyphSelectionType selectionType) { 
 
            GlyphCollection glyphs = new GlyphCollection();
 
            if (selectionType != GlyphSelectionType.NotSelected) {

                Point loc = BehaviorService.ControlToAdornerWindow((Control)Component);
                Rectangle translatedBounds = new Rectangle(loc, ((Control)Component).Size); 
                bool primarySelection = (selectionType == GlyphSelectionType.SelectedPrimary);
 
                bool locked = false; 
                PropertyDescriptor prop = TypeDescriptor.GetProperties(Component)["Locked"];
                if (prop != null) { 
                    locked = (bool)prop.GetValue(Component);
                }

                bool autoSize = false; 
                prop = TypeDescriptor.GetProperties(Component)["AutoSize"];
                if (prop != null) { 
                    autoSize = (bool)prop.GetValue(Component); 
                }
 
                AutoSizeMode mode = AutoSizeMode.GrowOnly;
                prop = TypeDescriptor.GetProperties(Component)["AutoSizeMode"];
                if (prop != null) {
                    mode = (AutoSizeMode)prop.GetValue(Component); 
                }
 
                SelectionRules rules = SelectionRules; 

                if (locked) { 
                    // the lock glyph
                    glyphs.Add(new LockedHandleGlyph(translatedBounds, primarySelection));

                    //the four locked border glyphs 
                    glyphs.Add(new LockedBorderGlyph(translatedBounds, SelectionBorderGlyphType.Top));
                    glyphs.Add(new LockedBorderGlyph(translatedBounds, SelectionBorderGlyphType.Bottom)); 
                    glyphs.Add(new LockedBorderGlyph(translatedBounds, SelectionBorderGlyphType.Left)); 
                    glyphs.Add(new LockedBorderGlyph(translatedBounds, SelectionBorderGlyphType.Right));
                } 
                // we check if the control is a form because we only want to disable resizing
                // for components that are not Forms.
                else if (autoSize && (mode == AutoSizeMode.GrowAndShrink) && !(Control is Form)) {
                    //the non-resizeable grab handle 
                    glyphs.Add(new NoResizeHandleGlyph(translatedBounds, rules, primarySelection, null));
 
                    //the four resizeable border glyphs 
                    glyphs.Add(new NoResizeSelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Top, null));
                    glyphs.Add(new NoResizeSelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Bottom, null)); 
                    glyphs.Add(new NoResizeSelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Left, null));
                    glyphs.Add(new NoResizeSelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Right, null));
                }
 
                else {
 
                    glyphs.Add(new GrabHandleGlyph(translatedBounds, GrabHandleGlyphType.MiddleRight, StandardBehavior, primarySelection)); 
                    glyphs.Add(new GrabHandleGlyph(translatedBounds, GrabHandleGlyphType.LowerRight, StandardBehavior, primarySelection));
                    glyphs.Add(new GrabHandleGlyph(translatedBounds, GrabHandleGlyphType.MiddleBottom, StandardBehavior, primarySelection)); 
                    glyphs.Add(new SelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Top, null));
                    glyphs.Add(new SelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Bottom, StandardBehavior));
                    glyphs.Add(new SelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Left, null));
                    glyphs.Add(new SelectionBorderGlyph(translatedBounds, rules, SelectionBorderGlyphType.Right, StandardBehavior)); 
                }
            } 
 
            return glyphs;
        } 

        /// 
        ///      Examines the current selection for a suitable frame designer.  This
        ///      is used when we are creating a new component so we know what control 
        ///      to parent the component to.  This will always return a frame designer,
        ///      and may walk all the way up the control parent chain to this designer 
        ///      if it needs to. 
        /// 
        private ParentControlDesigner GetSelectedParentControlDesigner() { 
            ISelectionService s = (ISelectionService)GetService(typeof(ISelectionService));
            ParentControlDesigner parentControlDesigner = null;

            if (s != null) { 
                // We first try the primary selection.  If that is null
                // or isn't a Control, we then walk the set of selected 
                // objects.  Failing all of this, we default to us. 
                //
                object sel = s.PrimarySelection; 

                if (sel == null || !(sel is Control)) {
                    sel = null;
 
                    ICollection sels = s.GetSelectedComponents();
 
                    foreach(object obj in sels) { 
                        if (obj is Control) {
                            sel = obj; 
                            break;
                        }
                    }
                } 

                if (sel != null) { 
                    // Now that we have our currently selected component 
                    // we can walk up the parent chain looking for a frame
                    // designer. 
                    //
                    Debug.Assert(sel is Control, "Our logic is flawed - sel should be a Control");
                    Control c = (Control)sel;
 
                    IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
 
                    if (host != null) { 
                        while (c != null) {
                            ParentControlDesigner designer = host.GetDesigner(c) as ParentControlDesigner; 

                            if (designer != null) {
                                parentControlDesigner = designer;
                                break; 
                            }
 
                            c = c.Parent; 
                        }
                    } 
                }
            }

            if (parentControlDesigner == null) { 
                parentControlDesigner = this;
            } 
 
            return parentControlDesigner;
        } 

        /// 
        /// 
        ///      Determines if the given tool is supported by this designer. 
        ///      If a tool is supported then it will be enabled in the toolbox
        ///      when this designer regains focus.  Otherwise, it will be disabled. 
        ///      Once a tool is marked as enabled or disabled it may not be 
        ///      queried again.
        ///  
        protected virtual bool GetToolSupported(ToolboxItem tool) {
            return true;
        }
 
        /// 
        ///  
        ///     Initializes the designer with the given component.  The designer can 
        ///     get the component's site and request services from it in this call.
        ///  
        public override void Initialize(IComponent component) {

            initializing = true;
            base.Initialize(component); 
            initializing = false;
 
            // If the back color of the control has not been established, force it to be 
            // "Control" so it doesn't walk up the parent chain and grab the document window's
            // back color. 
            //
            PropertyDescriptor backProp = TypeDescriptor.GetProperties(Component.GetType())["BackColor"];
            if (backProp != null && backProp.PropertyType == typeof(Color) && !backProp.ShouldSerializeValue(Component)) {
                Control.BackColor = SystemColors.Control; 
            }
 
            IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); 
            IExtenderProviderService exps = (IExtenderProviderService)GetService(typeof(IExtenderProviderService));
            if (exps != null) { 
                designerExtenders = new DesignerExtenders(exps);
            }

            if (host != null) { 
                host.Activated += new EventHandler(OnDesignerActivate);
                host.Deactivated += new EventHandler(OnDesignerDeactivate); 
 
                ServiceCreatorCallback callback = new ServiceCreatorCallback(this.OnCreateService);
                host.AddService(typeof(IEventHandlerService), callback); 

                // M3.2 CONTROL ARRAY IS CUT

                // Create the view for this component. We first create the designer frame so we can provide 
                // the overlay and split window services, and then later on we initilaize the frame with
                // the designer view. 
                // 
                frame = new DesignerFrame(component.Site);
 
                IOverlayService os = (IOverlayService)frame;
                host.AddService(typeof(IOverlayService), os);
                host.AddService(typeof(ISplitWindowService), frame);
 

                behaviorService = new BehaviorService(Component.Site, frame); 
                host.AddService(typeof(BehaviorService), behaviorService); 

                selectionManager = new SelectionManager(host, behaviorService); 

                host.AddService(typeof(SelectionManager), selectionManager);
                host.AddService(typeof(ToolStripAdornerWindowService), callback);
 
                // And component add and remove events for our tray
                // 
                IComponentChangeService cs = (IComponentChangeService)GetService(typeof(IComponentChangeService)); 
                    if (cs != null) {
                    cs.ComponentAdded += new ComponentEventHandler(this.OnComponentAdded); 
                    cs.ComponentChanged += new ComponentChangedEventHandler(this.OnComponentChanged);
                    cs.ComponentRemoved += new ComponentEventHandler(this.OnComponentRemoved);
                }
 
                // We must do the ineritance scan early, but not so early that we haven't hooked events
                // to handle invisible components.  We also use the variable "inheritanceService" 
                // as a check in OnCreateHandle -- we cannot call base.OnCreateHandle if we have 
                // not done an inheritance scan yet, because this will cause the base control
                // class to hook all of the controls we may want to inherit.  So, we do the 
                // scan, assign the variable, and then call OnCreateHandle if needed.
                //
                inheritanceUI = new InheritanceUI();
                host.AddService(typeof(InheritanceUI), inheritanceUI); 

                InheritanceService isvc = new DocumentInheritanceService(this); 
                host.AddService(typeof(IInheritanceService), isvc); 
                isvc.AddInheritedComponents(component, component.Site.Container);
                inheritanceService = isvc; 
                if (Control.IsHandleCreated) {
                    OnCreateHandle();
                }
 
                IPropertyValueUIService pvUISvc = (IPropertyValueUIService)component.Site.GetService(typeof(IPropertyValueUIService));
 
                if (pvUISvc != null) { 
                    designBindingValueUIHandler = new DesignBindingValueUIHandler();
                    pvUISvc.AddPropertyValueUIHandler(new PropertyValueUIHandler(designBindingValueUIHandler.OnGetUIValueItem)); 
                }

                // Add the DocumentDesigner as a creator of CLSID toolbox items.
                // 
                IToolboxService toolbox = (IToolboxService)host.GetService(typeof(IToolboxService));
                if (toolbox != null) { 
                    Debug.WriteLineIf(AxToolSwitch.TraceVerbose, "Adding DocumentDesigner as CLSID ToolboxItemCreator"); 
                    toolboxCreator = new ToolboxItemCreatorCallback(this.OnCreateToolboxItem);
                    toolbox.AddCreator(toolboxCreator, axClipFormat, host); 
                    toolbox.AddCreator(toolboxCreator, OleDragDropHandler.DataFormat, host);
                    toolbox.AddCreator(toolboxCreator, OleDragDropHandler.NestedToolboxItemFormat, host);
                }
 
                // Listen for the completed load.  When finished, we need to select the form.  We don'
                // want to do it before we're done, however, or else the dimensions of the selection rectangle 
                // could be off because during load, change events are not fired. 
                //
                host.LoadComplete += new EventHandler(this.OnLoadComplete); 
            }

            // Setup our menu command structure.
            // 
            Debug.Assert(component.Site != null, "Designer host should have given us a site by now.");
            commandSet = new ControlCommandSet(component.Site); 
 
            // Finally hook the designer view into the frame.  We do this last because the frame may
            // cause the control to be created, and if this happens before the inheritance scan we 
            // will subclass the inherited controls before we get a chance to attach designers.
            //
            frame.Initialize(Control);
            this.pbrsFwd = new PbrsForward(frame, component.Site); 

            // And force some shadow properties that we change in the course of 
            // initializing the form. 
            //
            Location = new Point(0, 0); 
        }

        /// 
        ///     Checks to see if the give CLSID is an ActiveX control 
        ///     that we support.  This ignores designtime controls.
        ///  
        private bool IsSupportedActiveXControl(string clsid) { 
            RegistryKey key = null;
            RegistryKey designtimeKey = null; 

            try {
                string controlKey = "CLSID\\" + clsid + "\\Control";
                key = Registry.ClassesRoot.OpenSubKey(controlKey); 
                if (key != null) {
 
                    // ASURT 36817: 
                    // We are not going to support design-time controls for this revision. We use the guids under
                    // HKCR\Component Categories to decide which categories to avoid. Currently the only one is 
                    // the "HTML Design-time Control" category implemented by VID controls.
                    //
                    string category = "CLSID\\" + clsid + "\\Implemented Categories\\{" + htmlDesignTime.ToString() + "}";
                    designtimeKey = Registry.ClassesRoot.OpenSubKey(category); 
                    return(designtimeKey == null);
                } 
 
                return false;
            } 
            finally {
                if (key != null)
                    key.Close();
 
                if (designtimeKey != null)
                    designtimeKey.Close(); 
            } 
        }
 
        private void OnUndone(object source, EventArgs e) {
            //resume all suspended comps we found earlier
            if (suspendedComponents != null) {
                foreach (Control c in suspendedComponents) { 
                    c.ResumeLayout(false/*performLayout*/);
                    c.PerformLayout(); 
                } 
            }
        } 

        private void OnUndoing(object source, EventArgs e) {
            // attempt to suspend all components within the icontainer
            // plus the root component's parent. 
            //
            IDesignerHost host = GetService(typeof(IDesignerHost)) as IDesignerHost; 
            if (host != null) { 
                IContainer container = host.Container;
                if (container != null) { 
                    suspendedComponents = new ArrayList(container.Components.Count + 1);

                    foreach (IComponent comp in container.Components) {
                        Control control = comp as Control; 
                        if (control != null) {
                            control.SuspendLayout(); 
                            //add this control to our suspended components list so we can resume 
                            //later
                            suspendedComponents.Add(control); 
                        }
                    }

                    // Also suspend the rooot component's parent. 
                    Control root = host.RootComponent as Control;
                    if (root != null) { 
                        Control rootParent = root.Parent as Control; 
                        if (rootParent != null) {
                            rootParent.SuspendLayout(); 
                            suspendedComponents.Add(rootParent);
                        }
                    }
                } 
            }
        } 
 
        /// 
        ///      Called when a component is added to the design container. 
        ///      If the component isn't a control, this will demand create
        ///      the component tray and add the component to it.
        /// 
        private void OnComponentAdded(object source, ComponentEventArgs ce) { 

            IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); 
            if (host != null) { 
                IComponent component = ce.Component;
 
                //if the component is a contextMenu - we'll start of the service
                EnsureMenuEditorService(ce.Component);

                bool addControl = true; 

                // This is the mirror to logic in ParentControlDesigner.  The component should be 
                // added somewhere, and this logic decides where. 
                //
 
                // LETS SEE IF WE ARE TOOLSTRIP in which case we want to get added
                // to the componentTray even though this is a control..
                // We should think of implementing an interface so that we can have many more
                // controls behaving like this. 
                //
                ToolStripDesigner td = host.GetDesigner(component) as ToolStripDesigner; 
 
                if (td == null) {
                    ControlDesigner cd = host.GetDesigner(component) as ControlDesigner; 
                    if (cd != null) {
                        Form form = cd.Control as Form;
                        if (form == null || !form.TopLevel) {
                            addControl = false; 
                        }
                    } 
                } 

                if (addControl && 
                    TypeDescriptor.GetAttributes(component).Contains(DesignTimeVisibleAttribute.Yes)) {

                    if (componentTray == null) {
                        ISplitWindowService sws = (ISplitWindowService)GetService(typeof(ISplitWindowService)); 
                        if (sws != null) {
                            componentTray = new ComponentTray(this, Component.Site); 
                            sws.AddSplitWindow(componentTray); 

                            componentTray.Height = trayHeight; 
                            componentTray.ShowLargeIcons = trayLargeIcon;
                            componentTray.AutoArrange = trayAutoArrange;

                            host.AddService(typeof(ComponentTray), componentTray); 
                        }
                    } 
 
                    if (componentTray != null) {
                        // Suspend the layout of the tray through the loading 
                        // process. This way, we won't continuosly try to layout
                        // components in auto arrange mode. We will instead let
                        // the controls restore themselves to their persisted state
                        // and then let auto-arrange kick in once. 
                        //
                        if (host != null && host.Loading && !trayLayoutSuspended) { 
                            trayLayoutSuspended = true; 
                            componentTray.SuspendLayout();
                        } 
                        componentTray.AddComponent(component);
                    }
                }
 

            } 
        } 

        ///  
        ///      Called when a component is removed from the design container.
        ///      Here we check to see there are no more components on the tray
        ///      and if not, we will remove the tray.
        ///  
        private void OnComponentRemoved(object source, ComponentEventArgs ce) {
            // ToolStrip is designableAsControl but has a ComponentTray Entry ... so special case it out. 
            bool designableAsControl = (ce.Component is Control && !(ce.Component is ToolStrip)) && !(ce.Component is Form && ((Form)ce.Component).TopLevel); 
            if (!designableAsControl && componentTray != null) {
                componentTray.RemoveComponent(ce.Component); 

                if (componentTray.ComponentCount == 0) {
                    ISplitWindowService sws = (ISplitWindowService)GetService(typeof(ISplitWindowService));
                    if (sws != null) { 
                        sws.RemoveSplitWindow(componentTray);
                        IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); 
                        if (host != null) { 
                            host.RemoveService(typeof(ComponentTray));
                        } 
                        componentTray.Dispose();
                        componentTray = null;
                    }
                } 
            }
 
 
        }
 
        /// 
        /// 
        ///     Called when the context menu should be displayed.  This displays the document
        ///     context menu. 
        /// 
        protected override void OnContextMenu(int x, int y) { 
            IMenuCommandService mcs = (IMenuCommandService)GetService(typeof(IMenuCommandService)); 
            if (mcs != null) {
                ISelectionService selSvc = (ISelectionService)GetService(typeof(ISelectionService)); 
                if (selSvc != null) {

                    // Here we check to see if we're the only component selected.  If not, then
                    // we'll display the standard component menu. 
                    //
                    if (selSvc.SelectionCount == 1 && selSvc.GetComponentSelected(Component)) { 
                        mcs.ShowContextMenu(MenuCommands.ContainerMenu, x, y); 
                    }
                    // Try to see if the component selected has a contextMenuStrip to show 
                    else
                    {
                        Component selComp = selSvc.PrimarySelection as Component;
                        if (selComp != null) 
                        {
                            IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); 
                            if (host != null) 
                            {
                                ComponentDesigner compDesigner = host.GetDesigner(selComp) as ComponentDesigner; 
                                if (compDesigner != null)
                                {
                                    compDesigner.ShowContextMenu(x, y);
                                    return; 
                                }
                            } 
                        } 
                        mcs.ShowContextMenu(MenuCommands.SelectionMenu, x, y);
                    } 

                }
            }
        } 

        ///  
        ///  
        ///      This is called immediately after the control handle has been created.
        ///  
        protected override void OnCreateHandle() {
            // Don't call base unless our inheritance serivce is already running.
            if (inheritanceService != null) {
                base.OnCreateHandle(); 
            }
        } 
 
        /// 
        ///     Creates some of the more infrequently used services we offer. 
        /// 
        private object OnCreateService(IServiceContainer container, Type serviceType) {
            if (serviceType == typeof(IEventHandlerService)) {
                if (eventHandlerService == null) { 
                    eventHandlerService = new EventHandlerService(frame);
                } 
                return eventHandlerService; 
            }
            else if (serviceType == typeof(ToolStripAdornerWindowService)) { 
                return new ToolStripAdornerWindowService(Component.Site, frame);
            }

 
            Debug.Fail("Called back to create a service we don't know how to create: " + serviceType.Name);
            return null; 
        } 

        ///  
        ///      Called when our document becomes active.  We paint our form's
        ///      border the appropriate color here.
        /// 
        private ToolboxItem OnCreateToolboxItem(object serializedData, string format) { 
            Debug.WriteLineIf(AxToolSwitch.TraceVerbose, "Checking to see if: " + format + " is supported.");
 
            IDataObject dataObject = serializedData as IDataObject; 

            if (dataObject == null) { 
                Debug.Fail("Toolbox service didn't pass us a data object; that should never happen");
                return null;
            }
 
            // CLSID format.
            // 
            if (format.Equals(axClipFormat)) { 
                return CreateAxToolboxItem(dataObject);
            } 

            // CF_CODE format
            //
            if (format.Equals(OleDragDropHandler.DataFormat) || 
                format.Equals(OleDragDropHandler.NestedToolboxItemFormat)) {
                return CreateCfCodeToolboxItem(dataObject); 
            } 

            return null; 
        }

        /// 
        ///      Called when our document becomes active.  Here we try to 
        ///      select the appropriate toolbox tab.
        ///  
        private void OnDesignerActivate(object source, EventArgs evevent) { 
            if (undoEngine == null) {
                undoEngine = GetService(typeof(UndoEngine)) as UndoEngine; 
                if (undoEngine != null) {
                    undoEngine.Undoing += new EventHandler(this.OnUndoing);
                    undoEngine.Undone += new EventHandler(this.OnUndone);
                } 
            }
        } 
 
        /// 
        ///     Called by the host when we become inactive.  Here we update the 
        ///     title bar of our form so it's the inactive color.
        /// 
        private void OnDesignerDeactivate(object sender, EventArgs e) {
            Control control = Control; 
            if (control != null && control.IsHandleCreated) {
                NativeMethods.SendMessage(control.Handle, NativeMethods.WM_NCACTIVATE, 0, 0); 
                SafeNativeMethods.RedrawWindow(control.Handle, null, IntPtr.Zero, NativeMethods.RDW_FRAME); 
            }
        } 


        /// 
        ///     Called when the designer is finished loading.  Here we select the form. 
        /// 
        private void OnLoadComplete(object sender, EventArgs e) { 
 
            // Remove the handler; we're done looking at this.
            // 
            ((IDesignerHost)sender).LoadComplete -= new EventHandler(this.OnLoadComplete);

            // Restore the tray layout.
            // 
            if (trayLayoutSuspended && componentTray != null)
                componentTray.ResumeLayout(); 
 
            // Select this component.
            // 
            ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService));
            if (ss != null) {
                ss.SelectionChanged += new EventHandler(this.OnSelectionChanged);
                ss.SetSelectedComponents(new object[] {Component}, SelectionTypes.Replace); 
                Debug.Assert(ss.PrimarySelection == Component, "Bug in selection service:  form should have primary selection.");
            } 
        } 

        private void OnComponentChanged(object sender, ComponentChangedEventArgs e) { 
            Control ctrl = e.Component as Control;
            if (ctrl != null && ctrl.IsHandleCreated) {
                UnsafeNativeMethods.NotifyWinEvent((int)AccessibleEvents.LocationChange, new HandleRef(ctrl, ctrl.Handle), NativeMethods.OBJID_CLIENT, 0);
                if (this.frame.Focused) { 
                    UnsafeNativeMethods.NotifyWinEvent((int)AccessibleEvents.Focus, new HandleRef(ctrl, ctrl.Handle), NativeMethods.OBJID_CLIENT, 0);
                } 
            } 
        }
 
        /// 
        ///      Called by the selection service when the selection has changed.  We do a number
        ///      of selection-related things here.
        ///  
        private void OnSelectionChanged(Object sender, EventArgs e) {
            ISelectionService svc = (ISelectionService)GetService( typeof(ISelectionService) ); 
            if (svc != null) { 

                ICollection selComponents = svc.GetSelectedComponents(); 

                // Setup the correct active accessibility selection / focus data
                //
                Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "MSAA: SelectionChanged"); 
                foreach(object selObj in selComponents) {
                    Control c = selObj as Control; 
                    if (c != null) { 
                        Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "MSAA: SelectionAdd, control = " + c.ToString());
                        UnsafeNativeMethods.NotifyWinEvent((int)AccessibleEvents.SelectionAdd, new HandleRef(c, c.Handle), NativeMethods.OBJID_CLIENT, 0); 
                    }
                }

                Control primary = svc.PrimarySelection as Control; 
                if (primary != null) {
                    Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "MSAA: Focus, control = " + primary.ToString()); 
                    UnsafeNativeMethods.NotifyWinEvent((int)AccessibleEvents.Focus, new HandleRef(primary, primary.Handle), NativeMethods.OBJID_CLIENT, 0); 
                }
 

                // see if there are visual controls selected.  If so, we add a context attribute.
                // Otherwise, we remove the attribute.  We do not count the form.
                // 
                IHelpService hs = (IHelpService)GetService(typeof(IHelpService));
 
                if (hs != null) { 
                    ushort type = 0;
                    string[] types = new string[] { 
                        "VisualSelection",
                        "NonVisualSelection",
                        "MixedSelection"
                    }; 

                    foreach(object obj in selComponents) { 
                        if (obj is Control) { 
                            if (obj != Component) {
                                type |= 1; 
                            }
                        }
                        else {
                            type |= 2; 
                        }
 
                        if (type == 3) { 
                            break;
                        } 
                    }

                    // Remove any prior attribute
                    // 
                    for (int i = 0; i < types.Length; i++) {
                        hs.RemoveContextAttribute("Keyword", types[i]); 
                    } 

                    if (type != 0) { 
                        hs.AddContextAttribute("Keyword", types[type - 1], HelpKeywordType.GeneralKeyword);
                    }

                } 
                // Activate / deactivate the menu editor.
                // 
                if (menuEditorService != null) 
                    DoProperMenuSelection(selComponents);
             } 
        }

        internal virtual void DoProperMenuSelection(ICollection selComponents) {
 
            foreach(object obj in selComponents) {
                ContextMenu cm = obj as ContextMenu; 
 
                if (cm != null) {
                    menuEditorService.SetMenu((Menu)obj); 
                }
                else {
                    MenuItem item = obj as MenuItem;
                    if (item != null) { 
                        //before we set the selection, we need to check if the item belongs the current menu,
                        //if not, we need to set the menu editor to the appropiate menu, then set selection 
                        // 
                        MenuItem parent = item;
                        while (parent.Parent is MenuItem) { 
                            parent = (MenuItem)parent.Parent;
                        }

                        if(menuEditorService.GetMenu() != parent.Parent) { 
                            menuEditorService.SetMenu(parent.Parent);
                        } 
 
                        //ok, here we have the correct editor selected for this item.
                        //Now, if there's only one item selected, then let the editor service know, 
                        //if there is more than one - then the selection was done through the
                        //menu editor and we don't need to tell it
                        if(selComponents.Count == 1) {
                            menuEditorService.SetSelection(item); 
                        }
                    } 
                    //Here, something is selected, but the menuservice isn't interested 
                    //so, we'll collapse our active menu accordingly
                    else menuEditorService.SetMenu(null); 
                }
            }
        }
 
        /// 
        ///  
        ///      Determines if a MenuEditorService has already been started.  If not, 
        ///      this method will create a new instance of the service.
        ///  
        protected virtual void EnsureMenuEditorService(IComponent c) {
            if (menuEditorService == null && c is ContextMenu) {
                menuEditorService = (IMenuEditorService)GetService(typeof(IMenuEditorService));
            } 
        }
 
        ///  
        /// 
        ///      Allows a designer to filter the set of properties 
        ///      the component it is designing will expose through the
        ///      TypeDescriptor object.  This method is called
        ///      immediately before its corresponding "Post" method.
        ///      If you are overriding this method you should call 
        ///      the base implementation before you perform your own
        ///      filtering. 
        ///  
        protected override void PreFilterProperties(IDictionary properties) {
            PropertyDescriptor prop; 

            base.PreFilterProperties(properties);

            // Add any properties that the Tray will persist. 
            properties["TrayHeight"] = TypeDescriptor.CreateProperty(typeof(DocumentDesigner), "TrayHeight", typeof(int),
                                                            BrowsableAttribute.No, 
                                                            DesignOnlyAttribute.Yes, 
                                                            new SRDescriptionAttribute("FormDocumentDesignerTraySizeDescr"),
                                                            CategoryAttribute.Design); 

            properties["TrayLargeIcon"] = TypeDescriptor.CreateProperty(typeof(DocumentDesigner), "TrayLargeIcon", typeof(bool),
                                                               BrowsableAttribute.No,
                                                               DesignOnlyAttribute.Yes, 
                                                               CategoryAttribute.Design);
 
            // Expose the doublebuffered property on control 
            properties["DoubleBuffered"] = TypeDescriptor.CreateProperty(typeof(Control), "DoubleBuffered", typeof(bool),
                                                                BrowsableAttribute.Yes, 
                                                                DesignOnlyAttribute.No);


            // Handle shadowed properties 
            //
            string[] shadowProps = new string[] { 
                    "Location", 
                    "BackColor"
                }; 

            string[] noBrowseProps = new string[] {
                "Anchor",
                "Dock", 
                "TabIndex",
                "TabStop", 
                "Visible" 
            };
 
            Attribute[] empty = new Attribute[0];

            for (int i = 0; i < shadowProps.Length; i++) {
                prop = (PropertyDescriptor)properties[shadowProps[i]]; 
                if (prop != null) {
                    properties[shadowProps[i]] = TypeDescriptor.CreateProperty(typeof(DocumentDesigner), prop, empty); 
                } 
            }
 
            prop = (PropertyDescriptor)properties["AutoScaleDimensions"];
            if (prop != null) {
                properties["AutoScaleDimensions"] = TypeDescriptor.CreateProperty(typeof(DocumentDesigner), prop, DesignerSerializationVisibilityAttribute.Visible);
            } 

            prop = (PropertyDescriptor)properties["AutoScaleMode"]; 
            if (prop != null) { 
                properties["AutoScaleMode"] = TypeDescriptor.CreateProperty(typeof(DocumentDesigner), prop, DesignerSerializationVisibilityAttribute.Visible, BrowsableAttribute.Yes);
            } 

            for (int i = 0; i < noBrowseProps.Length; i++) {
                prop = (PropertyDescriptor)properties[noBrowseProps[i]];
                if (prop != null) { 
                    properties[noBrowseProps[i]] = TypeDescriptor.CreateProperty(prop.ComponentType, prop, BrowsableAttribute.No, DesignerSerializationVisibilityAttribute.Hidden);
                } 
            } 
        }
 
        /// 
        ///     Resets the back color to be based on the parent's back color.
        /// 
        private void ResetBackColor() { 
            BackColor = Color.Empty;
        } 
 
        private bool ShouldSerializeAutoScaleDimensions() {
            // Visual inheritance always adds default 
            // value attributes that adopt the current values. This
            // isn't right for auto scale, however,because we always
            // want to write out the auto scale values.  So, we have
            // to be a bit sleazy here and trick the inheritance engine 
            // to think that these properties currently have their
            // default values. 
            return !initializing && AutoScaleMode != AutoScaleMode.None && AutoScaleMode != AutoScaleMode.Inherit; 
        }
 
        private bool ShouldSerializeAutoScaleMode() {
            // Visual inheritance always adds default
            // value attributes that adopt the current values. This
            // isn't right for auto scale, however,because we always 
            // want to write out the auto scale values.  So, we have
            // to be a bit sleazy here and trick the inheritance engine 
            // to think that these properties currently have their 
            // default values.
            return !initializing && ShadowProperties.Contains("AutoScaleMode"); 
        }

        /// 
        ///     Returns true if the BackColor property should be persisted in code gen. 
        /// 
        private bool ShouldSerializeBackColor() { 
            // We push Color.Empty into our shadow cash during 
            // init and also whenever we are reset.  We do this
            // so we can push a real color into the controls 
            // back color to stop it from walking the parent chain.
            // But, we want it to look like we didn't push a color
            // so code gen won't write out "Color.Control"
            if (!ShadowProperties.Contains("BackColor") || ((Color)ShadowProperties["BackColor"]).IsEmpty) { 
                return false;
            } 
 
            return true;
        } 

        /// 
        /// 
        ///      This will be called when the user double-clicks on a 
        ///      toolbox item.  The document designer should create
        ///      a component for the given tool. 
        ///  
        protected virtual void ToolPicked(ToolboxItem tool) {
 
            // If the tab order UI is showing, don't allow us to place a tool.
            //
            IMenuCommandService mcs = (IMenuCommandService)GetService(typeof(IMenuCommandService));
            if (mcs != null) { 
                MenuCommand cmd = mcs.FindCommand(StandardCommands.TabOrder);
                if (cmd != null && cmd.Checked) { 
                    return; 
                }
            } 

            IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
            if (host != null) {
                host.Activate(); 
            }
 
            // Just find the currently selected frame designer and ask it to create the tool. 
            //
            try { 
                ParentControlDesigner designer = GetSelectedParentControlDesigner();
                if (!InvokeGetInheritanceAttribute(designer).Equals(InheritanceAttribute.InheritedReadOnly)) {
                    InvokeCreateTool(designer, tool);
                    IToolboxService toolboxService = (IToolboxService)GetService(typeof(IToolboxService)); 
                    if (toolboxService != null) {
                        toolboxService.SelectedToolboxItemUsed(); 
                    } 
                }
            } 
            catch(Exception e) {
                DisplayError(e);
                if (ClientUtils.IsCriticalException(e)) {
                    throw; 
                }
            } 
 
            catch {
                Debug.Fail("non-CLS compliant exception"); 
            }
        }

        ///  
        /// 
        ///  
        /// The list of technologies that this designer can support 
        /// for its view.  Examples of different technologies are
        /// WinForms and Web Forms.  Other object models can be 
        /// supported at design time, but they most be able to
        /// provide a view in one of the supported technologies.
        /// 
        ViewTechnology[] IRootDesigner.SupportedTechnologies { 
            get {
                return new ViewTechnology[] {ViewTechnology.Default, (ViewTechnology)1}; 
            } 
        }
 
        /// 
        /// 
        /// 
        /// The view for this document.  The designer 
        /// should assume that the view will be shown shortly
        /// after this call is made and make any necessary 
        /// preparations. 
        /// 
 
        //We can live with this one. We have obsoleted some of the enum values. This method
        //only takes on argument, so it is pretty obvious what argument is bad.
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")]
        object IRootDesigner.GetView(ViewTechnology technology) { 
            if (technology != ViewTechnology.Default && technology != (ViewTechnology)1) {
                throw new ArgumentException(); 
            } 
            return frame;
        } 

        /// 
        /// 
        ///  
        /// Gets a value indicating whether the specified tool is supported by the current
        /// designer. 
        ///  
        //
        bool IToolboxUser.GetToolSupported(ToolboxItem tool) { 
            return GetToolSupported(tool);
        }

        ///  
        /// 
        ///  
        /// Selects the specified tool. 
        /// 
        void IToolboxUser.ToolPicked(ToolboxItem tool) { 
            ToolPicked(tool);
        }

 
        /// 
        ///     Handles the WM_WINDOWPOSCHANGING message 
        ///  
        /// 
        private unsafe void WmWindowPosChanged(ref Message m) { 

            NativeMethods.WINDOWPOS* wp = (NativeMethods.WINDOWPOS *)m.LParam;

            if ((wp->flags & NativeMethods.SWP_NOSIZE) == 0 && menuEditorService != null) { 
                BehaviorService.SyncSelection();
            } 
        } 

        ///  
        /// 
        ///      Overrides our base class WndProc to provide support for
        ///      the menu editor service.
        ///  
        protected override void WndProc(ref Message m) {
            if( menuEditorService != null) { 
                // We want to pass the messages to the menu editor unless the taborder view is active 
                // and the message will activate the menu editor (wm_ncXbuttondown messages)
                // 
                if (!(TabOrderActive && (m.Msg == NativeMethods.WM_NCLBUTTONDOWN || m.Msg == NativeMethods.WM_NCRBUTTONDOWN))) {
                    if(menuEditorService.MessageFilter(ref m)) {
                        return;
                    } 
                }
            } 
 
            base.WndProc(ref m);
 
            if (m.Msg == NativeMethods.WM_WINDOWPOSCHANGED) {
                WmWindowPosChanged(ref m);
            }
        } 

        // 
        //  
        // 
        //      Toolbox item we implement so we can create ActiveX controls. 
        // 
        // 
        // 
        [Serializable] 
        private class AxToolboxItem : ToolboxItem {
            private string clsid; 
            private Type axctlType = null; 
            private string version = String.Empty;
 
            public AxToolboxItem(string clsid) : base(typeof(AxHost)) {
                this.clsid = clsid;
                this.Company = null; //we don't get any company info for ax controls.
                LoadVersionInfo(); 
            }
 
            // Since we don't call the base constructor here, which does call Deserialize which we 
            // override, we should be okay.
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 
            private AxToolboxItem(SerializationInfo info, StreamingContext context) {
                Deserialize(info, context);

            } 

            ///  
            ///  
            ///     The Component Type is ".Net Component" -- unless otherwise specified by a derived toolboxitem
            ///  
            public override string ComponentType {
                get {
                    return SR.GetString(SR.Ax_Control);
                } 
            }
 
            public override string Version { 
                get {
                    return version; 
                }
            }

            private void LoadVersionInfo() { 
                string controlKey = "CLSID\\" + clsid;
                RegistryKey key = Registry.ClassesRoot.OpenSubKey(controlKey); 
 
                //fail later -- not for tooltip info...
                if (key != null) { 
                    RegistryKey verKey = key.OpenSubKey("Version");
                    if (verKey != null) {
                        version = (string)verKey.GetValue("");
                    } 
                }
            } 
 
            /// 
            ///  
            /// Creates an instance of the ActiveX control. Calls VS7 project system
            /// to generate the wrappers if they are needed..
            /// 
            protected override IComponent[] CreateComponentsCore(IDesignerHost host) { 
                IComponent[] comps = null;
                Debug.Assert(host != null, "Designer host is null!!!"); 
 
                // Get the DTE References object
                // 
                object references = GetReferences(host);
                if (references != null) {
                    try {
                        TYPELIBATTR tlibAttr = GetTypeLibAttr(); 

                        object[] args = new object[5]; 
                        args[0] = "{" + tlibAttr.guid.ToString() + "}"; 
                        args[1] = (int)tlibAttr.wMajorVerNum;
                        args[2] = (int)tlibAttr.wMinorVerNum; 
                        args[3] = (int)tlibAttr.lcid;

                        args[4] = "";
                        object tlbRef = references.GetType().InvokeMember("AddActiveX", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, references, args, CultureInfo.InvariantCulture); 
                        Debug.Assert(tlbRef != null, "Null reference returned by AddActiveX (tlbimp) by the project system for: " + clsid);
 
                        args[4] = "aximp"; 
                        object axRef = references.GetType().InvokeMember("AddActiveX", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, references, args, CultureInfo.InvariantCulture);
                        Debug.Assert(axRef != null, "Null reference returned by AddActiveX (aximp) by the project system for: " + clsid); 

                        axctlType = GetAxTypeFromReference(axRef, host);

                    } 
                    catch(TargetInvocationException tie) {
                        Debug.WriteLineIf(DocumentDesigner.AxToolSwitch.TraceVerbose, "Generating Ax References failed: " + tie.InnerException); 
                        throw tie.InnerException; 
                    }
                    catch(Exception e) { 
                        Debug.WriteLineIf(DocumentDesigner.AxToolSwitch.TraceVerbose, "Generating Ax References failed: " + e);
                        throw e;
                    }
                    catch { 
                        Debug.WriteLineIf(DocumentDesigner.AxToolSwitch.TraceVerbose, "Generating Ax References failed due to non-CLS compliant exception");
                        throw; 
                    } 
                }
 
                if (axctlType == null) {
                    IUIService uiSvc = (IUIService)host.GetService(typeof(IUIService));
                    if (uiSvc == null) {
                        RTLAwareMessageBox.Show(null, SR.GetString(SR.AxImportFailed), null, MessageBoxButtons.OK, MessageBoxIcon.Error, 
                                        MessageBoxDefaultButton.Button1, 0);
                    } 
                    else { 
                        uiSvc.ShowError(SR.GetString(SR.AxImportFailed));
                    } 
                    return new IComponent[0];
                }

                comps = new IComponent[1]; 
                try {
                    comps[0] = host.CreateComponent(axctlType); 
                } 
                catch (Exception e) {
                    Debug.Fail("Could not create type: " + e); 
                    throw e;
                }
                catch {
                    throw; 
                }
 
                Debug.Assert(comps[0] != null, "Could not create instance of ActiveX control wrappers!!!"); 
                return comps;
            } 

            /// 
            /// 
            /// Loads the state of this 'AxToolboxItem' 
            /// from the stream.
            ///  
            protected override void Deserialize(SerializationInfo info, StreamingContext context) { 
                base.Deserialize(info, context);
                clsid = info.GetString("Clsid"); 
            }

            /// 
            /// Gets hold of the DTE Reference object and from there, opens the assembly of the 
            /// ActiveX control we want to create. It then walks through all AxHost derived classes
            /// in that assembly, and returns the type that matches our control's CLSID. 
            ///  
            private Type GetAxTypeFromReference(object reference, IDesignerHost host) {
                string path = (string)reference.GetType().InvokeMember("Path", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, reference, null, CultureInfo.InvariantCulture); 

                // Missing reference will show up as an empty string.
                //
                if (path == null || path.Length <= 0) { 
                    return null;
                } 
 
                FileInfo file = new FileInfo(path);
                string fullPath = file.FullName; 
                Debug.WriteLineIf(AxToolSwitch.TraceVerbose, "Checking: " + fullPath);

                ITypeResolutionService trs = (ITypeResolutionService)host.GetService(typeof(ITypeResolutionService));
                Debug.Assert(trs != null, "No type resolution service found."); 

                Assembly a = trs.GetAssembly(AssemblyName.GetAssemblyName(fullPath)); 
                Debug.Assert(a != null, "No assembly found at " + fullPath); 

                return GetAxTypeFromAssembly(a); 
            }

            /// 
            /// Walks through all AxHost derived classes in the given assembly, 
            /// and returns the type that matches our control's CLSID.
            ///  
            private Type GetAxTypeFromAssembly(Assembly a) { 
                Type[] types = a.GetTypes();
                int len = types.Length; 
                for (int i = 0; i < len; ++i) {
                    Type t = types[i];
                    if (!(typeof(AxHost).IsAssignableFrom(t))) {
                        continue; 
                    }
 
                    object[] attrs = t.GetCustomAttributes(typeof(AxHost.ClsidAttribute), false); 
                    Debug.Assert(attrs != null && attrs.Length == 1, "Invalid number of GuidAttributes found on: " + t.FullName);
 
                    AxHost.ClsidAttribute guid = (AxHost.ClsidAttribute)attrs[0];
                    if (String.Equals(guid.Value, clsid,  StringComparison.OrdinalIgnoreCase)) {
                        return t;
                    } 
                }
 
                return null; 
            }
 
            /// 
            /// Gets the References collection object from the designer host. The steps are:
            ///     Get the ProjectItem from the IDesignerHost.
            ///     Get the Containing Project of the ProjectItem. 
            ///     Get the VSProject of the Containing Project.
            ///     Get the References property of the VSProject. 
            ///  
            private object GetReferences(IDesignerHost host) {
                Debug.Assert(host != null, "Null Designer Host"); 

                Type type;
                object ext = null;
                type = Type.GetType("EnvDTE.ProjectItem, " + AssemblyRef.EnvDTE); 

                if (type == null) { 
                    return null; 
                }
 
                ext = host.GetService(type);
                if (ext == null)
                    return null;
 
                string name = ext.GetType().InvokeMember("Name", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, ext, null, CultureInfo.InvariantCulture).ToString();
 
                object project = ext.GetType().InvokeMember("ContainingProject", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, ext, null, CultureInfo.InvariantCulture); 
                Debug.Assert(project != null, "No DTE Project for the current project item: " + name);
 
                object vsproject = project.GetType().InvokeMember("Object", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, project, null, CultureInfo.InvariantCulture);
                Debug.Assert(vsproject != null, "No VS Project for the current project item: " + name);

                object references = vsproject.GetType().InvokeMember("References", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, vsproject, null, CultureInfo.InvariantCulture); 
                Debug.Assert(references != null, "No References for the current project item: " + name);
 
                return references; 
            }
 
            /// 
            /// Gets the TypeLibAttr corresponding to the TLB containing our ActiveX control.
            /// 
            private TYPELIBATTR GetTypeLibAttr() { 
                string controlKey = "CLSID\\" + clsid;
                RegistryKey key = Registry.ClassesRoot.OpenSubKey(controlKey); 
                if (key == null) { 
                    if (DocumentDesigner.AxToolSwitch.TraceVerbose) Debug.WriteLine("No registry key found for: " + controlKey);
                    throw new ArgumentException(SR.GetString(SR.AXNotRegistered, controlKey.ToString())); 
                }

                // Load the typelib into memory.
                // 
                ITypeLib pTLB = null;
 
                // Try to get the TypeLib's Guid. 
                //
                Guid tlbGuid = Guid.Empty; 

                // Open the key for the TypeLib
                //
                RegistryKey tlbKey = key.OpenSubKey("TypeLib"); 

                if (tlbKey != null) { 
                    // Get the major and minor version numbers. 
                    //
                    RegistryKey verKey = key.OpenSubKey("Version"); 
                    Debug.Assert(verKey != null, "No version registry key found for: " + controlKey);

                    short majorVer = -1;
                    short minorVer = -1; 
                    string ver = (string)verKey.GetValue("");
                    int dot = ver.IndexOf('.'); 
                    if (dot == -1) { 
                        majorVer = Int16.Parse(ver, CultureInfo.InvariantCulture);
                        minorVer = 0; 
                    }
                    else {
                        majorVer = Int16.Parse(ver.Substring(0, dot), CultureInfo.InvariantCulture);
                        minorVer = Int16.Parse(ver.Substring(dot + 1, ver.Length - dot - 1), CultureInfo.InvariantCulture); 
                    }
                    Debug.Assert(majorVer > 0 && minorVer >= 0, "No Major version number found for: " + controlKey); 
                    verKey.Close(); 

                    object o = tlbKey.GetValue(""); 
                    tlbGuid = new Guid((string)o);
                    Debug.Assert(!tlbGuid.Equals(Guid.Empty), "No valid Guid found for: " + controlKey);
                    tlbKey.Close();
 
                    try {
                        pTLB = NativeMethods.LoadRegTypeLib(ref tlbGuid, majorVer, minorVer, Application.CurrentCulture.LCID); 
                    } 
                    catch (Exception e) {
                        if (AxWrapperGen.AxWrapper.Enabled) Debug.WriteLine("Failed to LoadRegTypeLib: " + e.ToString()); 
                        if (ClientUtils.IsCriticalException(e)) {
                            throw;
                        }
                    } 
                    catch {
                        Debug.Fail("non-CLS compliant exception"); 
                    } 

                } 

                // Try to load the TLB directly from the InprocServer32.
                //
                // If that fails, try to load the TLB based on the TypeLib guid key. 
                //
                if (pTLB == null) { 
                    RegistryKey inprocServerKey = key.OpenSubKey("InprocServer32"); 
                    if (inprocServerKey != null) {
                        string inprocServer = (string)inprocServerKey.GetValue(""); 
                        Debug.Assert(inprocServer != null, "No valid InprocServer32 found for: " + controlKey);
                        inprocServerKey.Close();

                        pTLB = NativeMethods.LoadTypeLib(inprocServer); 
                    }
                } 
 
                key.Close();
 
                if (pTLB != null) {
                    try {
                        IntPtr pTlibAttr = NativeMethods.InvalidIntPtr;
                        pTLB.GetLibAttr(out pTlibAttr); 
                        if (pTlibAttr == NativeMethods.InvalidIntPtr)
                            throw new ArgumentException(SR.GetString(SR.AXNotRegistered, controlKey.ToString())); 
                        else { 
                            // Marshal the returned int as a TLibAttr structure
                            // 
                            TYPELIBATTR typeLibraryAttributes = (TYPELIBATTR) Marshal.PtrToStructure(pTlibAttr, typeof(TYPELIBATTR));
                            pTLB.ReleaseTLibAttr(pTlibAttr);

                            return typeLibraryAttributes; 
                        }
                    } 
                    finally { 
                        Marshal.ReleaseComObject(pTLB);
                    } 
                }
                else {
                    throw new ArgumentException(SR.GetString(SR.AXNotRegistered, controlKey.ToString()));
                } 

            } 
 
            /// 
            ///  
            /// Saves the state of this 'AxToolboxItem' to
            ///    the specified serialization info.
            /// 
            protected override void Serialize(SerializationInfo info, StreamingContext context) { 
                if (DocumentDesigner.AxToolSwitch.TraceVerbose) Debug.WriteLine("Serializing AxToolboxItem:" + clsid);
                base.Serialize(info, context); 
                info.AddValue("Clsid", clsid); 
            }
        } 

        /// 
        ///      Document designer's version of the inheritance service.  For UI
        ///      components, we will allow private controls if those controls are 
        ///      children of our document, since they will be visible.
        ///  
        private class DocumentInheritanceService : InheritanceService { 
            private DocumentDesigner designer;
 
            /// 
            /// 
            ///      Creates a new document inheritance service.
            ///  
            public DocumentInheritanceService(DocumentDesigner designer) {
                this.designer = designer; 
            } 

            ///  
            /// 
            ///    Indicates the inherited members to ignore.
            /// 
            protected override bool IgnoreInheritedMember(MemberInfo member, IComponent component) { 

                // We allow private members if they are controls on our design surface or 
                // derive from Menu. 
                //
                bool privateMember = false; 
                Type memberType = null;

                FieldInfo field = member as FieldInfo;
                MethodInfo method = member as MethodInfo; 
                if (field != null) {
                    privateMember = field.IsPrivate || field.IsAssembly; 
                    memberType = field.FieldType; 
                }
                else if (method != null) { 
                    privateMember = method.IsPrivate || method.IsAssembly;
                    memberType = method.ReturnType;
                }
                else { 
                    Debug.Fail("Unknown member type passed to IgnoreInheritedMember");
                    return true; 
                } 

                if (privateMember) { 
                    if (typeof(Control).IsAssignableFrom(memberType)) {
                        // See if this member is a child of our document...
                        //
                        Control child = null; 
                        if (field != null) {
                            child = (Control)field.GetValue(component); 
                        } 
                        else if (method != null) {
                            child = (Control)method.Invoke(component, null); 
                        }
                        Control parent = designer.Control;

                        while (child != null && child != parent) { 
                            child = child.Parent;
                        } 
 
                        // If it is a child of our designer, we don't want to ignore this member.
                        // 
                        if (child != null) {
                            return false;
                        }
                    } 
                    else if (typeof(Menu).IsAssignableFrom(memberType)) {
                        object menu = null; 
                        if (field != null) { 
                            menu = field.GetValue(component);
                        } 
                        else if (method != null) {
                            menu = method.Invoke(component, null);
                        }
                        if (menu != null) { 
                            return false;
                        } 
                    } 
                }
 
                return base.IgnoreInheritedMember(member, component);
            }
        }
    } 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

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