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] |