[Mmclibrary-svn] SF.net SVN: mmclibrary: [9] MMCLib2/Core/SnapinBase.cs
Brought to you by:
imjimmurphy,
kachalkov
From: <tig...@us...> - 2008-06-09 09:07:17
|
Revision: 9 http://mmclibrary.svn.sourceforge.net/mmclibrary/?rev=9&view=rev Author: tigerharry Date: 2008-06-09 02:06:56 -0700 (Mon, 09 Jun 2008) Log Message: ----------- - creating _component in constructor - added property ToolBar - added property ToolbarImageIndex - added property ToolbarButtons ==> now it's easy to add a toolBar Modified Paths: -------------- MMCLib2/Core/SnapinBase.cs Modified: MMCLib2/Core/SnapinBase.cs =================================================================== --- MMCLib2/Core/SnapinBase.cs 2008-06-06 14:22:50 UTC (rev 8) +++ MMCLib2/Core/SnapinBase.cs 2008-06-09 09:06:56 UTC (rev 9) @@ -18,1070 +18,1122 @@ namespace Ironring.MMC.Core { - /// <summary> - /// The Base class for the snapin object implements the IComponentData interface that is the primary - /// communication conduit to MMC. Contains our IComponent implementation as well to handle the other - /// part of the MMC dialog. This class also contains the master collection of Nodes and will dispatch - /// to the appropriate Node when notifications arrive. All nodes must register back to this class on - /// creation for registration in the master collection. This happen automatically in the BaseNode - /// contructor. - /// </summary> - public class SnapinBase : - //Added by Alexander Kachalkov - //Allow marshaling from the Property Sheet thread - //using Invoke method - System.Windows.Forms.Control - ,IComponentData - ,IExtendPropertySheet - ,IExtendContextMenu - ,IPersistStream - { - /// <summary> - /// Master list of all Nodes displayed in the snapin - /// this collection "owns" them and assignes cookie values - /// </summary> - protected HybridDictionary _nodes = new HybridDictionary(8); + /// <summary> + /// The Base class for the snapin object implements the IComponentData interface that is the primary + /// communication conduit to MMC. Contains our IComponent implementation as well to handle the other + /// part of the MMC dialog. This class also contains the master collection of Nodes and will dispatch + /// to the appropriate Node when notifications arrive. All nodes must register back to this class on + /// creation for registration in the master collection. This happen automatically in the BaseNode + /// contructor. + /// </summary> + public class SnapinBase : + //Added by Alexander Kachalkov + //Allow marshaling from the Property Sheet thread + //using Invoke method + System.Windows.Forms.Control + , IComponentData + , IExtendPropertySheet + , IExtendContextMenu + , IPersistStream + { + /// <summary> + /// Master list of all Nodes displayed in the snapin + /// this collection "owns" them and assignes cookie values + /// </summary> + protected HybridDictionary _nodes = new HybridDictionary(8); - /////////////////////////////////////////////////////////////////////// - // - // Private vars - // - #region + /////////////////////////////////////////////////////////////////////// + // + // Private vars + // + #region - /// <summary> - /// We only want to see one Manager per Snapin - /// </summary> - private bool _showSnapinManager = true; + /// <summary> + /// We only want to see one Manager per Snapin + /// </summary> + private bool _showSnapinManager = true; - /// <summary> - /// Contained object that implements IComponent on our behalf - /// </summary> - private Component _component = null; + /// <summary> + /// Contained object that implements IComponent on our behalf + /// </summary> + private Component _component = null; - private IConsole2 _console = null; - private IConsoleNameSpace2 _consoleNameSpace = null; - private int _nodeId = 0; - private BaseNode _currentScopeNode; - private ImageList _images = new ImageList(); - private BaseNode _selectedNodes = null; - private IntPtr _handle; - private System.Windows.Forms.ContextMenu _filterMenu; - private static ResourceManager _translator; - private MMC_VERSION _mmcVersion; - #endregion + private IConsole2 _console = null; + private IConsoleNameSpace2 _consoleNameSpace = null; + private int _nodeId = 0; + private BaseNode _currentScopeNode; + private ImageList _images = new ImageList(); + private BaseNode _selectedNodes = null; + private IntPtr _handle; + private System.Windows.Forms.ContextMenu _filterMenu; + private static ResourceManager _translator; + private MMC_VERSION _mmcVersion; + #endregion - /////////////////////////////////////////////////////////////////////// - // - // Properties - // - #region - // Added by MAM - /// <summary> - /// Get or set the scope node that is currently selected for this snapin. This is needed - /// for component.cs which goes through hoops to get the currently selected - /// ScopeNode. - /// </summary> - public BaseNode CurrentScopeNode - { - get { return _currentScopeNode; } - set { _currentScopeNode = value; } - } + /////////////////////////////////////////////////////////////////////// + // + // Properties + // + #region + // Added by MAM + /// <summary> + /// Get or set the scope node that is currently selected for this snapin. This is needed + /// for component.cs which goes through hoops to get the currently selected + /// ScopeNode. + /// </summary> + public BaseNode CurrentScopeNode + { + get { return _currentScopeNode; } + set { _currentScopeNode = value; } + } - //Added by Alexander Kachalkov - /// <summary> - /// returns global images collection - /// Using it from Component class while creating Toolbar. - /// </summary> - public ImageList Images - { - get { return _images; } - } + //added by Harald Binkle [tigerharry] + //give access to component to be able to add toolbars + public Component Component + { + get + { + return _component; + } + } - /// <summary> - /// Returns if there is a scope node selected - /// </summary> - public virtual bool ScopeNodeSelected - { - get { return _selectedNodes != null; } - } - /// <summary> - /// Get the set of selected scope nodes. In MMC this always returns 0 or 1 nodes. - /// </summary> - public virtual BaseNode SelectedScopeNodes - { - get { return _selectedNodes; } - } + //added by Harald Binkle [tigerharry] + public MMCBUTTON[] ToolbarButtons + { + get + { + return _component.ToolbarButtons; + } + set + { + _component.ToolbarButtons = value; + } + } - /// <summary> - /// returns if there is a view-item selected - /// </summary> - public virtual bool ViewItemSelected - { - get - { - ReportNode rne = _currentScopeNode as ReportNode; - if(rne != null) - { - return rne.GetCurrentSelected().Length != 0; - } - else - { - return false; - } - } - } + //added by Harald Binkle [tigerharry] + public int ToolbarImageIndex + { + get + { + return _component.ToolbarImageIndex; + } + set + { + _component.ToolbarImageIndex = value; + } + } - /// <summary> - /// Get the last selected scope node. This is the node that is currently active, - /// or the last node that was clicked before focus was transfered to the result-pane. - /// </summary> - public virtual BaseNode LastSelectedScopeNode - { - get { return _currentScopeNode; } - } + //added by Harald Binkle [tigerharry] + public IToolbar ToolBar + { + get + { + return _component.ToolBar; + } + } - /// <summary> - /// Get all selected items in the result-pane. - /// </summary> - /// <remarks>In the current incarnation of MMCLib/MMCLib2 - /// there is no multiselection possible. This is not a guarantee - /// that it won't be possible to do it in the future though! - /// </remarks> - public ResultViewItem[] SelectedViewItems - { - get - { - ArrayList retval = new ArrayList(); - ReportNode rne = _currentScopeNode as ReportNode; - if(rne != null) - return rne.GetCurrentSelected(); - else - return new ResultViewItem[0]; - } - } - - /// <summary> - /// returns the window handle that the control is bound to. - /// </summary> - public IntPtr SnapinHandle - { - get {return _handle;} - } - /// <summary> - /// - /// </summary> - public System.Windows.Forms.ContextMenu FilterMenu - { - get { return _filterMenu; } - set { _filterMenu = value; } - } + //Added by Alexander Kachalkov + /// <summary> + /// returns global images collection + /// Using it from Component class while creating Toolbar. + /// </summary> + public ImageList Images + { + get { return _images; } + } - /// <summary> - /// Cached MMCVersion - /// </summary> - public MMC_VERSION MMCVersion - { - get{ return _mmcVersion;} - set{ _mmcVersion = value; } - } + /// <summary> + /// Returns if there is a scope node selected + /// </summary> + public virtual bool ScopeNodeSelected + { + get { return _selectedNodes != null; } + } - #endregion + /// <summary> + /// Get the set of selected scope nodes. In MMC this always returns 0 or 1 nodes. + /// </summary> + public virtual BaseNode SelectedScopeNodes + { + get { return _selectedNodes; } + } - /// <summary> - /// Add the node to the currently active nodes in the snapin. - /// </summary> - /// <param name="bn">The node to add</param> - internal void AddSelectedNode(BaseNode bn) - { - _currentScopeNode = bn; + /// <summary> + /// returns if there is a view-item selected + /// </summary> + public virtual bool ViewItemSelected + { + get + { + ReportNode rne = _currentScopeNode as ReportNode; + if (rne != null) + { + return rne.GetCurrentSelected().Length != 0; + } + else + { + return false; + } + } + } - _selectedNodes = bn; - } + /// <summary> + /// Get the last selected scope node. This is the node that is currently active, + /// or the last node that was clicked before focus was transfered to the result-pane. + /// </summary> + public virtual BaseNode LastSelectedScopeNode + { + get { return _currentScopeNode; } + } - /// <summary> - /// Remove the given node as active from the snapin. - /// </summary> - /// <param name="bn">The node to remove. (not used, preparing for multiselect)</param> - internal void RemoveSelectedNode(BaseNode bn) - { - _selectedNodes = null; - } + /// <summary> + /// Get all selected items in the result-pane. + /// </summary> + /// <remarks>In the current incarnation of MMCLib/MMCLib2 + /// there is no multiselection possible. This is not a guarantee + /// that it won't be possible to do it in the future though! + /// </remarks> + public ResultViewItem[] SelectedViewItems + { + get + { + ArrayList retval = new ArrayList(); + ReportNode rne = _currentScopeNode as ReportNode; + if (rne != null) + return rne.GetCurrentSelected(); + else + return new ResultViewItem[0]; + } + } - /// <summary> - /// Static function to help with internationalisation - /// </summary> - internal static string Translate(string key) - { - if(_translator == null) - _translator = new ResourceManager("Ironring.MMC.Resources.i18n", - System.Reflection.Assembly.GetExecutingAssembly()); - return _translator.GetString(key); - } + /// <summary> + /// returns the window handle that the control is bound to. + /// </summary> + public IntPtr SnapinHandle + { + get { return _handle; } + } - ////////////////////////////////////////////////////////////////////////// - // - // SnapinBase Implementation - // - #region - /// <summary> - /// Default Constructor - /// </summary> - public SnapinBase() - { - InitializeComponent(); - // Get the window handle and keep it alive, as long as the MMC is. - _handle = Handle; - this.SnapinState = CreateSnapinState(); - System.Diagnostics.Debug.WriteLine("Snapin<init>"); - } + /// <summary> + /// + /// </summary> + public System.Windows.Forms.ContextMenu FilterMenu + { + get { return _filterMenu; } + set { _filterMenu = value; } + } - /// <summary> - /// return the guid for the snapin - dig it out of the Guid attribute in the base class! - /// Gotta love reflection. - /// </summary> - public Guid Guid - { - get - { - object[] attrs = GetType().GetCustomAttributes(typeof(GuidAttribute), true); - if (attrs.Length == 0) - throw new SnapinException("Failed ot find GuidAttribute on SnapinBase class"); + /// <summary> + /// Cached MMCVersion + /// </summary> + public MMC_VERSION MMCVersion + { + get { return _mmcVersion; } + set { _mmcVersion = value; } + } - return new Guid(((GuidAttribute)attrs[0]).Value); - } - } + #endregion - /// <summary> - /// get/set the root node - this starts off the population of the entire - /// namespace. The RootNode is also known as the static node in MMC. It - /// will be queried for its children. - /// </summary> - public BaseNode RootNode - { - get { return (BaseNode)_nodes[0]; } - set { _nodes[0] = value; } - } + /// <summary> + /// Add the node to the currently active nodes in the snapin. + /// </summary> + /// <param name="bn">The node to add</param> + internal void AddSelectedNode(BaseNode bn) + { + _currentScopeNode = bn; - /// <summary> - /// Return the Componenet's console - /// </summary> - public IConsole2 ResultViewConsole - { - get { return _component.Console; } - } + _selectedNodes = bn; + } - /// <summary> - /// Return the cached member variable to get at MMC - /// </summary> - public IConsole2 Console - { - get { return _console; } - } + /// <summary> + /// Remove the given node as active from the snapin. + /// </summary> + /// <param name="bn">The node to remove. (not used, preparing for multiselect)</param> + internal void RemoveSelectedNode(BaseNode bn) + { + _selectedNodes = null; + } - /// <summary> - /// Return the cached member variable to get at MMC - /// </summary> - public IConsoleNameSpace2 ConsoleNameSpace - { - get { return _consoleNameSpace; } - } + /// <summary> + /// Static function to help with internationalisation + /// </summary> + internal static string Translate(string key) + { + if (_translator == null) + _translator = new ResourceManager("Ironring.MMC.Resources.i18n", + System.Reflection.Assembly.GetExecutingAssembly()); + return _translator.GetString(key); + } - /// <summary> - /// Return the cached member variable to get at MMC - /// </summary> - public IHeaderCtrl2 HeaderCtrl - { - get { return (IHeaderCtrl2)_console; } - } + ////////////////////////////////////////////////////////////////////////// + // + // SnapinBase Implementation + // + #region + /// <summary> + /// Default Constructor + /// </summary> + public SnapinBase() + { + InitializeComponent(); + // Get the window handle and keep it alive, as long as the MMC is. + _handle = Handle; + this.SnapinState = CreateSnapinState(); + //added by Harald Binkle [tigerharry] + //create component to be able to add toolbars + IComponent comp; + CreateComponent(out comp); + + System.Diagnostics.Debug.WriteLine("Snapin<init>"); + } - //Added by Alexander Kachalkov - /// <summary> - /// Overridable helper method to GetSelectedItem - /// </summary> - /// <param name="ResultData"></param> - public virtual RESULTDATAITEM GetSelectedItem(IResultData resultData) - { - return GetSelectedItem(resultData, -1); // nIndex == -1 to start at first item - } + /// <summary> + /// return the guid for the snapin - dig it out of the Guid attribute in the base class! + /// Gotta love reflection. + /// </summary> + public Guid Guid + { + get + { + object[] attrs = GetType().GetCustomAttributes(typeof(GuidAttribute), true); + if (attrs.Length == 0) + throw new SnapinException("Failed ot find GuidAttribute on SnapinBase class"); - /// <summary> - /// Overridable helper method to GetSelectedItem - /// </summary> - /// <param name="ResultData"></param> - /// <param name="nIndex"></param> - public virtual RESULTDATAITEM GetSelectedItem(IResultData resultData, int nIndex) - { - RESULTDATAITEM rdi = new RESULTDATAITEM(); + return new Guid(((GuidAttribute)attrs[0]).Value); + } + } - rdi.mask = (uint)RDI.STATE; // nState is valid - rdi.nCol = 0; - rdi.nIndex = nIndex; // nIndex == -1 to start at first item - rdi.nState = (uint)LVIS.SELECTED; // only interested in selected items + /// <summary> + /// get/set the root node - this starts off the population of the entire + /// namespace. The RootNode is also known as the static node in MMC. It + /// will be queried for its children. + /// </summary> + public BaseNode RootNode + { + get { return (BaseNode)_nodes[0]; } + set { _nodes[0] = value; } + } - try - { - resultData.GetNextItem(ref rdi); - } - catch(Exception) - { - // FIXME: (Lesley) - // I get an error while selecting a resultnode - // I think it's because nothing is selected yet - // that's why we catch the exception and won't handle it - // maybe it's better to return null - } - //out - return rdi; - } - /// <summary> - /// find a node with the given cookie in our master index - /// </summary> - /// <param name="cookie"></param> - /// <returns></returns> - public BaseNode FindNode(int cookie) - { - // some nodes use the high order word for item id - // so mask off this word to get the "real" cookie. - int cleanCookie = cookie & 0xffff; - BaseNode node = (BaseNode)_nodes[cleanCookie]; - if (node == null) - throw new SnapinException("Failed to find Node with cookie " + cleanCookie.ToString()); + /// <summary> + /// Return the Componenet's console + /// </summary> + public IConsole2 ResultViewConsole + { + get { return _component.Console; } + } - return node; - } - - /// <summary> - /// find a node by the MMC defined HScopeID - /// </summary> - /// <param name="HScopeID"></param> - /// <returns></returns> - public BaseNode FindNodeByHScope(int hScopeID) - { - foreach(BaseNode node in _nodes.Values) - { - if (node.HScopeItem == hScopeID) - return node; - } - return null; - } + /// <summary> + /// Return the cached member variable to get at MMC + /// </summary> + public IConsole2 Console + { + get { return _console; } + } - /// <summary> - /// called be BaseNode constructor to register itself back here for - /// centralized lookup when MMC want to talk to a Node - /// </summary> - /// <param name="newNode"></param> - /// <returns></returns> - public int Register(BaseNode newNode) - { - // return the index in the array - that is opaque to the node - it shouldn't - // make any assumptions about the value - thats our job in this class. - // We may change the collection strategy in the future if we need to - // support bigger node sets. - int id = _nodeId; - _nodes.Add(id, newNode); - _nodeId++; - return id; - } - - //Added by Alexander Kachalkov - /// <summary> - /// Unregister node - /// </summary> - /// <param name="node"></param> - public void Unregister(BaseNode node) - { - _nodes.Remove(node.Cookie); - //Added by Alexander Ovchinnikov - node.RemovePropertySheet( ); - } + /// <summary> + /// Return the cached member variable to get at MMC + /// </summary> + public IConsoleNameSpace2 ConsoleNameSpace + { + get { return _consoleNameSpace; } + } - /// <summary> - /// Add a string representing the embedded resource name of an icon to - /// the snapin's global image coolection - /// </summary> - /// <param name="iconResourceName"></param> - public int AddImage(string iconResourceName) - { - return _images.Add(iconResourceName); - } - - //Added by Alexander Kachalkov - /// <summary> - /// Add a string representing the embedded resource name of an icon to - /// the snapin's global image coolection - /// </summary> - /// <param name="iconResourceName"></param> - /// <param name="transparentColor">Specifies the TransparentColor of the image to be loaded and appended</param> - /// <returns></returns> - public int AddImage(string iconResourceName, Color transparentColor) - { - return _images.Add(iconResourceName, transparentColor); - } + /// <summary> + /// Return the cached member variable to get at MMC + /// </summary> + public IHeaderCtrl2 HeaderCtrl + { + get { return (IHeaderCtrl2)_console; } + } - /// <summary> - /// Add a loaded and initialized icon to the snapin global image collection - /// </summary> - /// <param name="icon"></param> - public int AddImage(Icon icon) - { - return _images.Add(icon); - } - #endregion - ////////////////////////////////////////////////////////////////////// - // - // IComponentData implementation - // - #region - /// <summary> - /// Called by MMC with the Console interface on startup we do snapin one time init stuff here - /// </summary> - /// <param name="pUnknown">Implements IConsole()2 and IConsoleNameSpace2 interfaces</param> - public void Initialize(Object pUnknown) - { - try - { - // cache references to MMC interfaces - _console = (IConsole2)pUnknown; - _consoleNameSpace = (IConsoleNameSpace2)pUnknown; + //Added by Alexander Kachalkov + /// <summary> + /// Overridable helper method to GetSelectedItem + /// </summary> + /// <param name="ResultData"></param> + public virtual RESULTDATAITEM GetSelectedItem(IResultData resultData) + { + return GetSelectedItem(resultData, -1); // nIndex == -1 to start at first item + } - // alow startup init for each node - foreach(BaseNode node in _nodes.Values) - node.Initialize(); + /// <summary> + /// Overridable helper method to GetSelectedItem + /// </summary> + /// <param name="ResultData"></param> + /// <param name="nIndex"></param> + public virtual RESULTDATAITEM GetSelectedItem(IResultData resultData, int nIndex) + { + RESULTDATAITEM rdi = new RESULTDATAITEM(); - // Now we'll add the images we need for the snapin - IImageList il = null; - _console.QueryScopeImageList(out il); - - // add the snapin - global images to the scope pane - _images.LoadImageList(il); + rdi.mask = (uint)RDI.STATE; // nState is valid + rdi.nCol = 0; + rdi.nIndex = nIndex; // nIndex == -1 to start at first item + rdi.nState = (uint)LVIS.SELECTED; // only interested in selected items - // forward to the root node to see if any nodes care to add their node specific - // icons to the image list - RootNode.OnAddScopePaneImages(il); - } - catch(Exception e) - { - System.Diagnostics.Debug.WriteLine("Initialize failed - " + e.Message); - ceh.OnThreadException(this, new ThreadExceptionEventArgs(e)); - throw e; - } - } + try + { + resultData.GetNextItem(ref rdi); + } + catch (Exception) + { + // FIXME: (Lesley) + // I get an error while selecting a resultnode + // I think it's because nothing is selected yet + // that's why we catch the exception and won't handle it + // maybe it's better to return null + } + //out + return rdi; + } + /// <summary> + /// find a node with the given cookie in our master index + /// </summary> + /// <param name="cookie"></param> + /// <returns></returns> + public BaseNode FindNode(int cookie) + { + // some nodes use the high order word for item id + // so mask off this word to get the "real" cookie. + int cleanCookie = cookie & 0xffff; + BaseNode node = (BaseNode)_nodes[cleanCookie]; + if (node == null) + throw new SnapinException("Failed to find Node with cookie " + cleanCookie.ToString()); - // MAM: made virtual. - /// <summary> - /// Give MMC our IComponent implementation when asked - /// </summary> - /// <param name="ppComponent">a pointer to out Component object</param> - public virtual void CreateComponent(out IComponent ppComponent) - { - // Make sure we don't already have a component created - if (_component == null) - _component = new Component(this); + return node; + } - ppComponent = _component; - } + /// <summary> + /// find a node by the MMC defined HScopeID + /// </summary> + /// <param name="HScopeID"></param> + /// <returns></returns> + public BaseNode FindNodeByHScope(int hScopeID) + { + foreach (BaseNode node in _nodes.Values) + { + if (node.HScopeItem == hScopeID) + return node; + } + return null; + } - /// <summary> - /// This notify is primarily responsible for inserting data items into - /// the console namespace. - /// </summary> - /// <param name="lpDataObject">the node to notify</param> - /// <param name="aevent">notification type</param> - /// <param name="arg">optional event context</param> - /// <param name="param">optional event context</param> - /// <returns></returns> - public int Notify(IDataObject lpDataObject, uint aevent, IntPtr arg, IntPtr param) - { - int hr = HRESULT.S_OK; + /// <summary> + /// called be BaseNode constructor to register itself back here for + /// centralized lookup when MMC want to talk to a Node + /// </summary> + /// <param name="newNode"></param> + /// <returns></returns> + public int Register(BaseNode newNode) + { + // return the index in the array - that is opaque to the node - it shouldn't + // make any assumptions about the value - thats our job in this class. + // We may change the collection strategy in the future if we need to + // support bigger node sets. + int id = _nodeId; + _nodes.Add(id, newNode); + _nodeId++; + return id; + } - try - { - DataObject test = (DataObject)lpDataObject; - BaseNode node = (test == null) ? RootNode : test.Node; + //Added by Alexander Kachalkov + /// <summary> + /// Unregister node + /// </summary> + /// <param name="node"></param> + public void Unregister(BaseNode node) + { + _nodes.Remove(node.Cookie); + //Added by Alexander Ovchinnikov + node.RemovePropertySheet(); + } - // TBD: add more events and dispatch to virtual methods instead? or event fire events? + /// <summary> + /// Add a string representing the embedded resource name of an icon to + /// the snapin's global image coolection + /// </summary> + /// <param name="iconResourceName"></param> + public int AddImage(string iconResourceName) + { + return _images.Add(iconResourceName); + } - MMCN_Notify notify = (MMCN_Notify)aevent; + //Added by Alexander Kachalkov + /// <summary> + /// Add a string representing the embedded resource name of an icon to + /// the snapin's global image coolection + /// </summary> + /// <param name="iconResourceName"></param> + /// <param name="transparentColor">Specifies the TransparentColor of the image to be loaded and appended</param> + /// <returns></returns> + public int AddImage(string iconResourceName, Color transparentColor) + { + return _images.Add(iconResourceName, transparentColor); + } - System.Diagnostics.Debug.WriteLine("IComponentData::Notify - " + notify.ToString()); + /// <summary> + /// Add a loaded and initialized icon to the snapin global image collection + /// </summary> + /// <param name="icon"></param> + public int AddImage(Icon icon) + { + return _images.Add(icon); + } + #endregion + ////////////////////////////////////////////////////////////////////// + // + // IComponentData implementation + // + #region + /// <summary> + /// Called by MMC with the Console interface on startup we do snapin one time init stuff here + /// </summary> + /// <param name="pUnknown">Implements IConsole()2 and IConsoleNameSpace2 interfaces</param> + public void Initialize(Object pUnknown) + { + try + { + // cache references to MMC interfaces + _console = (IConsole2)pUnknown; + _consoleNameSpace = (IConsoleNameSpace2)pUnknown; - switch(notify) - { - // If a data item is expanding, we need to tell MMC about it's children. - // Note, this case doesn't necessarily mean the data item is expanding - // visually.... MMC is just requesting information about it. - case MMCN_Notify.EXPAND: - { - if ((int)arg != 0) - { - if (node.HScopeItem == 0) - node.HScopeItem = (int)param; - node.OnExpand(); - } - else - { - node.OnCollapse(); - } - break; - } - //---added by Roman Kiss - case MMCN_Notify.DELETE: - { - node.OnDelete(); - break; - } - //Added by Alexander Kachalkov - case MMCN_Notify.BTN_CLICK: - { - // CmdID of the button equal to a value of the MMC_COMMANDS enum type. - int cmdid = param.ToInt32(); - node.OnBtnClick(cmdid); - break; - } - //Added by Alexander Kachalkov - case MMCN_Notify.RENAME: - { - // can we rename? - if ((int)arg == 0) - { - // can we rename? - if (!node.OnTryRename()) - hr = HRESULT.S_FALSE; - } - // rename editing complete - here is the string - else // arg == 1 - { - // is the renamed value ok? - if (!node.OnRename(Marshal.PtrToStringAuto(param))) - hr = HRESULT.S_FALSE; - } + // alow startup init for each node + foreach (BaseNode node in _nodes.Values) + node.Initialize(); - break; - } - default: - { - // We didn't handle the message - hr = HRESULT.S_FALSE; - break; - } - } - } - - catch(SnapinException) - { - hr = HRESULT.S_FALSE; - } - catch(Exception e) - { - //Added by Lesley van Zijl - //MMC will eat the throw - System.Diagnostics.Debug.WriteLine(e.Message); - ceh.OnThreadException(this, new ThreadExceptionEventArgs(e)); - throw e; - - } + // Now we'll add the images we need for the snapin + IImageList il = null; + _console.QueryScopeImageList(out il); - return hr; - } + // add the snapin - global images to the scope pane + _images.LoadImageList(il); - /// <summary> - /// Called by MMC to cleanup - /// TBD: call Dispose - after that pattern is more pervaisivly used - /// </summary> - public virtual void Destroy() - { - } + // forward to the root node to see if any nodes care to add their node specific + // icons to the image list + RootNode.OnAddScopePaneImages(il); + } + catch (Exception e) + { + System.Diagnostics.Debug.WriteLine("Initialize failed - " + e.Message); + ceh.OnThreadException(this, new ThreadExceptionEventArgs(e)); + throw e; + } + } - /// <summary> - /// The IComponentData::QueryDataObject method returns a data object that can be used to retrieve - /// the context information for the specified cookie. - /// </summary> - /// <param name="cookie">Specifies the unique identifier for which the data object is required.</param> - /// <param name="type">Specifies the data object as one of the members of the CCT enum</param> - /// <param name="ppDataObject">Pointer to the address of the returned data object</param> - public virtual void QueryDataObject(int cookie, uint type, out IDataObject ppDataObject) - { - if(type == (uint)CCT.SNAPIN_MANAGER && _showSnapinManager) - { - System.Diagnostics.Debug.WriteLine("Asks for Snapin Manager in SnapinBase"); - // false so that it doesn't show up again - _showSnapinManager = false; - this.ShowInitialisationWizard(); - } - ppDataObject = new DataObject(FindNode(cookie)); - } + // MAM: made virtual. + /// <summary> + /// Give MMC our IComponent implementation when asked + /// </summary> + /// <param name="ppComponent">a pointer to out Component object</param> + public virtual void CreateComponent(out IComponent ppComponent) + { + // Make sure we don't already have a component created + if (_component == null) + _component = new Component(this); - #region MMC SNAPIN MANAGER - // This is how it works: - // If you load a snapin in the MMC (so a not saved snapin(.msc)) the mmc sends a msg to the - // Snapin with the question 'do you have a SnapinManager for me?' - // as this happens we set up our wizard, and we make sure that the Wizard is shown once. - // after that we let the base Class handle the QueryDataObject - // - // you could use a SnapinManager for Startup configuration, like the Microsoft Services plugin - // it asks if you want to connect to a remote server or want work on the local machine. - protected virtual void ShowInitialisationWizard() - { - if(this.Managers != null) - { - WizardBase.ShowWizard( this.ManagerTitle, - this.Managers, - new WizardBase.WizardAction(ManagerHandler)); - } - } + ppComponent = _component; + } - public virtual WizardPage[] Managers - { - get{return null;} - } + /// <summary> + /// This notify is primarily responsible for inserting data items into + /// the console namespace. + /// </summary> + /// <param name="lpDataObject">the node to notify</param> + /// <param name="aevent">notification type</param> + /// <param name="arg">optional event context</param> + /// <param name="param">optional event context</param> + /// <returns></returns> + public int Notify(IDataObject lpDataObject, uint aevent, IntPtr arg, IntPtr param) + { + int hr = HRESULT.S_OK; - protected String m_managerTitle; - public virtual String ManagerTitle - { - get{return m_managerTitle;} - set{m_managerTitle = value;} - } + try + { + DataObject test = (DataObject)lpDataObject; + BaseNode node = (test == null) ? RootNode : test.Node; - // This is the method that handles the finish of the Wizard, in this example it does nothing - // but this method could send data to a remote server or could adjust some nodes, be creative :) - protected virtual void ManagerHandler(Ironring.MMC.Wizards.WizardPage[] pages) - { - } - #endregion + // TBD: add more events and dispatch to virtual methods instead? or event fire events? - /// <summary> - /// provides scope pane info to MMC - /// </summary> - /// <param name="sdi"></param> - public virtual void GetDisplayInfo(ref SCOPEDATAITEM sdi) - { - // First let's find this node we want info on.... - BaseNode NodeWeWant = FindNode(sdi.lParam); - NodeWeWant.GetDisplayInfo(ref sdi); - } + MMCN_Notify notify = (MMCN_Notify)aevent; - - /// <summary> - /// This method will compare two data objects based on underlying cookie value - /// that the nodes contain - /// </summary> - /// <param name="lpDataObjectA"></param> - /// <param name="lpDataObjectB"></param> - /// <returns></returns> - public int CompareObjects(IDataObject lpDataObjectA, IDataObject lpDataObjectB) - { - // since this is the only type we hand out it should be the only type - // provided here and the cast should "always" work. + System.Diagnostics.Debug.WriteLine("IComponentData::Notify - " + notify.ToString()); - DataObject doItem1 = (DataObject)lpDataObjectA; - DataObject doItem2 = (DataObject)lpDataObjectB; + switch (notify) + { + // If a data item is expanding, we need to tell MMC about it's children. + // Note, this case doesn't necessarily mean the data item is expanding + // visually.... MMC is just requesting information about it. + case MMCN_Notify.EXPAND: + { + if ((int)arg != 0) + { + if (node.HScopeItem == 0) + node.HScopeItem = (int)param; + node.OnExpand(); + } + else + { + node.OnCollapse(); + } + break; + } + //---added by Roman Kiss + case MMCN_Notify.DELETE: + { + node.OnDelete(); + break; + } + //Added by Alexander Kachalkov + case MMCN_Notify.BTN_CLICK: + { + // CmdID of the button equal to a value of the MMC_COMMANDS enum type. + int cmdid = param.ToInt32(); + node.OnBtnClick(cmdid); + break; + } + //Added by Alexander Kachalkov + case MMCN_Notify.RENAME: + { + // can we rename? + if ((int)arg == 0) + { + // can we rename? + if (!node.OnTryRename()) + hr = HRESULT.S_FALSE; + } + // rename editing complete - here is the string + else // arg == 1 + { + // is the renamed value ok? + if (!node.OnRename(Marshal.PtrToStringAuto(param))) + hr = HRESULT.S_FALSE; + } - // TBD: implement IComparable on Node and compare cookies. + break; + } + default: + { + // We didn't handle the message + hr = HRESULT.S_FALSE; + break; + } + } + } - // These are different objects. We need to return S_FALSE - if (doItem1.Node.Cookie != doItem2.Node.Cookie) - return HRESULT.S_FALSE; + catch (SnapinException) + { + hr = HRESULT.S_FALSE; + } + catch (Exception e) + { + //Added by Lesley van Zijl + //MMC will eat the throw + System.Diagnostics.Debug.WriteLine(e.Message); + ceh.OnThreadException(this, new ThreadExceptionEventArgs(e)); + throw e; - return HRESULT.S_OK; - } - #endregion - ////////////////////////////////////////////////////////////////////// - // - // IExtendPropertySheet implementation - // - #region - /// <summary> - /// MMC wants a property sheet created of the given node - /// </summary> - /// <param name="lpProvider"></param> - /// <param name="handle"></param> - /// <param name="lpDataObject"></param> - /// <returns></returns> - public virtual int CreatePropertyPages(IPropertySheetCallback lpProvider, IntPtr handle, IDataObject lpDataObject) - { - DataObject dataObject = (DataObject)lpDataObject; - try - { - if(this.ScopeNodeSelected == false) - { - // Show the property pages for all nodes - ReportNode rpne = (ReportNode)dataObject.Node; - rpne.CreatePropertyPagesForItems(lpProvider, handle); + } - // See comment below! - return HRESULT.S_FALSE; - } - else - { - IMMCSaneNode sane = (IMMCSaneNode)dataObject.Node; - if(sane.PropertyPages.Count == 0) - return HRESULT.S_FALSE; - else - { - // Got pages. - dataObject.Node.PropertyPages.Clear(); - dataObject.Node.CreatePropertyPages(lpProvider, handle); - - // We have created our own property-pages in a separate thread. - // DON'T LET MMC DISPLAY A PROPERTY PAGE TOO! This is needed for - // Winforms to work. - return HRESULT.S_FALSE; - } - } - } - catch(Exception e) - { - System.Diagnostics.Debug.WriteLine("SnapinBaseExt::CreatePropertyPages exception: " + e); - ceh.OnThreadException(this, new ThreadExceptionEventArgs(e)); - } - // don't use the MMC property page facilities - just roll our own. - return HRESULT.S_FALSE; - } + return hr; + } - /// <summary> - /// MMC calls this at initialization time to find out if the node - /// supports property pages - this is the one and only time to respond. - /// This is overriden to get the property-page of the item or node - /// that is currently selected. - /// </summary> - /// <param name="lpDataObject">IdataObject for Node in question</param> - /// <returns></returns> - public virtual int QueryPagesFor(IDataObject lpDataObject) - { - // This snapin does have property pages, so we should return S_OK - // (which will happen automatically). If the snapin didn't have - // any property pages, then we should return S_FALSE + /// <summary> + /// Called by MMC to cleanup + /// TBD: call Dispose - after that pattern is more pervaisivly used + /// </summary> + public virtual void Destroy() + { + } - DataObject dataObject = (DataObject)lpDataObject; - - //---added by Roman Kiss - dataObject.Node.OnQueryProperties(); + /// <summary> + /// The IComponentData::QueryDataObject method returns a data object that can be used to retrieve + /// the context information for the specified cookie. + /// </summary> + /// <param name="cookie">Specifies the unique identifier for which the data object is required.</param> + /// <param name="type">Specifies the data object as one of the members of the CCT enum</param> + /// <param name="ppDataObject">Pointer to the address of the returned data object</param> + public virtual void QueryDataObject(int cookie, uint type, out IDataObject ppDataObject) + { + if (type == (uint)CCT.SNAPIN_MANAGER && _showSnapinManager) + { + System.Diagnostics.Debug.WriteLine("Asks for Snapin Manager in SnapinBase"); + // false so that it doesn't show up again + _showSnapinManager = false; + this.ShowInitialisationWizard(); + } + ppDataObject = new DataObject(FindNode(cookie)); + } - // Let's see if this node has property pages - try - { - // When there are items in the selection, we assume the properties are for those. - if(this.ScopeNodeSelected == false) - { - ReportNode rpne = dataObject.Node as ReportNode; - if(rpne != null) - { - if(rpne.ItemsHavePropertyPages()) - { - return HRESULT.S_OK; - } - } - return HRESULT.S_FALSE; - } - else - { - IMMCSaneNode sane = (IMMCSaneNode)dataObject.Node; - if(sane.PropertyPages.Count != 0) - return HRESULT.S_OK; - } - } - catch(Exception e) - { - System.Diagnostics.Debug.WriteLine("SnapinBase::QueryPagesFor exception: " + e); - ceh.OnThreadException(this, new ThreadExceptionEventArgs(e)); - } + #region MMC SNAPIN MANAGER + // This is how it works: + // If you load a snapin in the MMC (so a not saved snapin(.msc)) the mmc sends a msg to the + // Snapin with the question 'do you have a SnapinManager for me?' + // as this happens we set up our wizard, and we make sure that the Wizard is shown once. + // after that we let the base Class handle the QueryDataObject + // + // you could use a SnapinManager for Startup configuration, like the Microsoft Services plugin + // it asks if you want to connect to a remote server or want work on the local machine. + protected virtual void ShowInitialisationWizard() + { + if (this.Managers != null) + { + WizardBase.ShowWizard(this.ManagerTitle, + this.Managers, + new WizardBase.WizardAction(ManagerHandler)); + } + } - return HRESULT.S_FALSE; - } - #endregion - ////////////////////////////////////////////////////////////////////// - // - // IExtendContextMenu implementation - // - #region - /// <summary> - /// Add menu items based on MMC's insertion rules - /// </summary> - /// <param name="piDataObject"></param> - /// <param name="piCallback"></param> - /// <param name="pInsertionAllowed"></param> - public void AddMenuItems(IntPtr piDataObject, IContextMenuCallback piCallback, ref int pInsertionAllowed) - { - DataObject item = null; - try - { - //Added by Alexander Kachalkov - IDataObject iDataObject = (IDataObject)Marshal.GetObjectForIUnknown(piDataObject); - - // The piDataObject is really a DataObject in disguise.... - item = (DataObject)iDataObject; + public virtual WizardPage[] Managers + { + get { return null; } + } - if (item.Node != null) - item.Node.AddMenuItems(piCallback, ref pInsertionAllowed); - } - catch(SnapinException e) - { - System.Diagnostics.Debug.WriteLine("SnapinBase::AddMenuItems SnapinException - " + e.ToString()); - ceh.OnThreadException(this, new ThreadExceptionEventArgs(e)); - // eat the exception and return s_false indicating that - // we didn't handle the notification - //throw e; - } - catch(Exception e) - { - System.Diagnostics.Debug.WriteLine("SnapinBase::AddMenuItems Exception - " + e.ToString()); - ceh.OnThreadException(this, new ThreadExceptionEventArgs(e)); - //throw e; - } - } + protected String m_managerTitle; + public virtual String ManagerTitle + { + get { return m_managerTitle; } + set { m_managerTitle = value; } + } - // FIXME: http://sourceforge.net/tracker/index.php?func=detail&aid=832805&group_id=93348&atid=604010 - // public void AddMenuItems(IntPtr iDataObject, IContextMenuCallback piCallback, ref int pInsertionAllowed) - // { - // if (iDataObject == (IntPtr) DataObject.CUSTOMOCX || iDataObject == (IntPtr)DataObject.CUSTOMWEB) - // { - // } - // else - // { - // - // IDataObject piDataObject = (IDataObject)Marshal.GetObjectForIUnknown(iDataObject); - // - // // The piDataObject is really a DataObject is disguise.... - // - // DataObject item = (DataObject)piDataObject; - // - // if (item.Node != null) - // item.Node.AddMenuItems(piCallback, ref pInsertionAllowed); - // } - // } + // This is the method that handles the finish of the Wizard, in this example it does nothing + // but this method could send data to a remote server or could adjust some nodes, be creative :) + protected virtual void ManagerHandler(Ironring.MMC.Wizards.WizardPage[] pages) + { + } + #endregion + /// <summary> + /// provides scope pane info to MMC + /// </summary> + /// <param name="sdi"></param> + public virtual void GetDisplayInfo(ref SCOPEDATAITEM sdi) + { + // First let's find this node we want info on.... + BaseNode NodeWeWant = FindNode(sdi.lParam); + NodeWeWant.GetDisplayInfo(ref sdi); + } + /// <summary> + /// This method will compare two data objects based on underlying cookie value + /// that the nodes contain + /// </summary> + /// <param name="lpDataObjectA"></param> + /// <param name="lpDataObjectB"></param> + /// <returns></returns> + public int CompareObjects(IDataObject lpDataObjectA, IDataObject lpDataObjectB) + { + // since this is the only type we hand out it should be the only type + // provided here and the cast should "always" work. + DataObject doItem1 = (DataObject)lpDataObjectA; + DataObject doItem2 = (DataObject)lpDataObjectB; + // TBD: implement IComparable on Node and compare cookies. + // These are different objects. We need to return S_FALSE + if (doItem1.Node.Cookie != doItem2.Node.Cookie) + return HRESULT.S_FALSE; - /// <summary> - /// Called when user invokes a menu command - /// </summary> - /// <param name="lCommandID"></param> - /// <param name="piDataObject"></param> - public void Command(int lCommandID, IntPtr piDataObject) - { - DataObject item = null; - try - { - //Added by Alexander Kachalkov - IDataObject iDataObject = (IDataObject)Marshal.GetObjectForIUnknown(piDataObject); - - // The piDataObject is really a DataObject is disguise.... - item = (DataObject)iDataObject; + return HRESULT.S_OK; + } + #endregion + ////////////////////////////////////////////////////////////////////// + // + // IExtendPropertySheet implementation + // + #region + /// <summary> + /// MMC wants a property sheet created of the given node + /// </summary> + /// <param name="lpProvider"></param> + /// <param name="handle"></param> + /// <param name="lpDataObject"></param> + /// <returns></returns> + public virtual int CreatePropertyPages(IPropertySheetCallback lpProvider, IntPtr handle, IDataObject lpDataObject) + { + DataObject dataObject = (DataObject)lpDataObject; + try + { + if (this.ScopeNodeSelected == false) + { + // Show the property pages for all nodes + ReportNode rpne = (ReportNode)dataObject.Node; + rpne.CreatePropertyPagesForItems(lpProvider, handle); - // pass the command on to the node - if (item.Node != null) - item.Node.Command(lCommandID); - } - catch(SnapinException e) - { - System.Diagnostics.Debug.WriteLine("SnapinBase::AddMenuItems SnapinException - " + e.ToString()); - ceh.OnThreadException(this, new ThreadExceptionEventArgs(e)); - // eat the exception and return s_false indicating that - // we didn't handle the notification - //throw e; - } - catch(Exception e) - { - System.Diagnostics.Debug.WriteLine("SnapinBase::AddMenuItems Exception - " + e.ToString()); - ceh.OnThreadException(this, new ThreadExceptionEventArgs(e)); - //throw e; - } - } - #endregion + // See comment below! + return HRESULT.S_FALSE; + } + else + { + IMMCSaneNode sane = (IMMCSaneNode)dataObject.Node; + if (sane.PropertyPages.Count == 0) + return HRESULT.S_FALSE; + else + { + // Got pages. + dataObject.Node.PropertyPages.Clear(); + dataObject.Node.CreatePropertyPages(lpProvider, handle); - /// <summary> - /// Auto Register the snap-in with MMC - /// </summary> - [ComRegisterFunction()] - public static void RegisterSnapIn(Type t) - { - SnapinRegistrar.Register(t.Assembly); - } + // We have created our own property-pages in a separate thread. + // DON'T LET MMC DISPLAY A PROPERTY PAGE TOO! This is needed for + // Winforms to work. + return HRESULT.S_FALSE; + } + } + } + catch (Exception e) + { + System.Diagnostics.Debug.WriteLine("SnapinBaseExt::CreatePropertyPages exception: " + e); + ceh.OnThreadException(this, new ThreadExceptionEventArgs(e)); + } + // don't use the MMC property page facilities - just roll our own. + return HRESULT.S_FALSE; + } - /// <summary> - /// Unregister the snap-in with MMC - /// </summary> - [ComUnregisterFunction()] - public static void UnregisterSnapIn(Type t) - { - SnapinRegistrar.UnRegister(t.Assembly); - } + /// <summary> + /// MMC calls this at initialization time to find out if the node + /// supports property pages - this is the one and only time to respond. + /// This is overriden to get the property-page of the item or node + /// that is currently selected. + /// </summary> + /// <param name="lpDataObject">IdataObject for Node in question</param> + /// <returns></returns> + public virtual int QueryPagesFor(IDataObject lpDataObject) + { + // This snapin does have property pages, so we should return S_OK + // (which will happen automatically). If the snapin didn't have + // any property pages, then we should return S_FALSE - private void InitializeComponent() - { - this.FilterMenu = new System.Windows.Forms.ContextMenu(); - } + DataObject dataObject = (DataObject)lpDataObject; - ////////////////////////////////////////////////////////////////////// - // - // IPersistStream implementation. - // - #region - /// <summary> - /// The state for this snapin. - /// </summary> - protected SnapinStateBase m_SnapinState; - public virtual SnapinStateBase SnapinState - { - get { return this.m_SnapinState; } - set { this.m_SnapinState = value; } - } + //---added by Roman Kiss + dataObject.Node.OnQueryProperties(); - /// <summary> - /// Normaly IPersistStreamInit would be used. This doesn't - /// seem to work though. Instead we fake the init. Our - /// init() will call this method to get a default SnapinState. - /// Override when needed. - /// </summary> - /// <returns></returns> - public virtual SnapinStateBase CreateSnapinState() - { - SnapinStateBase ssb = new SnapinStateBase(); - return ssb; - } - - /// <summary> - /// Get the class-id for this snapin. - /// </summary> - /// <param name="pClassID"></param> - public void GetClassID(out Guid pClassID) - { - System.Diagnostics.Debug.WriteLine("GetClassID"); - pClassID = this.Guid; - } - - /// <summary> - /// Check if the snapin-state is dirty. - /// </summary> - /// <returns></returns> - public int IsDirty( ) - { - System.Diagnostics.Debug.WriteLine("IsDirty"); - if(this.SnapinState != null) - { - if(this.SnapinState.Dirty) - { - return 0; - } - else - { - return 1; - } - } - else - { - return 1; - } - } + // Let's see if this node has property pages + try + { + // When there are items in the selection, we assume the properties are for those. + if (this.ScopeNodeSelected == false) + { + ReportNode rpne = dataObject.Node as ReportNode; + if (rpne != null) + { + if (rpne.ItemsHavePropertyPages()) + { + return HRESULT.S_OK; + } + } + return HRESULT.S_FALSE; + } + else + { + IMMCSaneNode sane = (IMMCSaneNode)dataObject.Node; + if (sane.PropertyPages.Count != 0) + return HRESULT.S_OK; + } + } + catch (Exception e) + { + System.Diagnostics.Debug.WriteLine("SnapinBase::QueryPagesFor exception: " + e); + ceh.OnThreadException(this, new ThreadExceptionEventArgs(e)); + } - /// <summary> - /// Delegate back to the snapin-state for de-serializing. - /// </summary> - /// <param name="pStm"></param> - public void Load(IStream pStm) - { - try - { - System.Diagnostics.Debug.WriteLine("Load"); - ComStream cs = new ComStream(pStm); - this.SnapinState.ReadState(cs); - cs.Close(); - System.Diagnostics.Debug.WriteLine("Loaded state: " + this.SnapinState); - } - catch(Exception e) - { - System.Diagnostics.Debug.WriteLine("Exception in load: " + e); - ceh.OnThreadException(this, new ThreadExceptionEventArgs(e)); - } - } + return HRESULT.S_FALSE; + } + #endregion + ////////////////////////////////////////////////////////////////////// + // + // IExtendContextMenu implementation + // + #region + /// <summary> + /// Add menu items based on MMC's insertion rules + /// </summary> + /// <param name="piDataObject"></param> + /// <param name="piCallback"></param> + /// <param name="pInsertionAllowed"></param> + public void AddMenuItems(IntPtr piDataObject, IContextMenuCallback piCallback, ref int pInsertionAllowed) + { + DataObject item = null; + try + { + //Added by Alexander Kachalkov + IDataObject iDataObject = (IDataObject)Marshal.GetObjectForIUnknown(piDataObject); - /// <summary> - /// Delegate back to the snapin-state for serialization. - /// </summary> - /... [truncated message content] |