代码之家  ›  专栏  ›  技术社区  ›  jonny

.NET自定义窗体设计器:如何实现IMenuCommandService?

  •  3
  • jonny  · 技术社区  · 15 年前

    我有一个很久以前为一个数据库项目编写的报表设计器。它使用了大量的WiAPI魔法,因此我不得不以适当的方式重写某些部件。

    感谢msdn杂志的一些文章( here here ) CodeProject 我能够实现设计器曲面、工具箱和撤消/重做引擎。

    1. 到目前为止,我在这个话题上发现的每一个资源都有点过时。你能指一下新鲜的/全面的文章吗?

    2. 代码来自 article 上面提到的似乎不起作用。

      调用了menucommandservice.showcontextmenu,但未显示任何内容,因为globalberbs集合中没有任何designerverbs。我是否应该手动添加与设计器操作(如剪切/粘贴)相对应的“标准”操作?如果是的话,我怎样才能做到这一点呢?

    2 回复  |  直到 15 年前
        1
  •  3
  •   jonny    15 年前

    多亏了SharpDevelop的消息,我才想出了解决办法。

    这个最小的实现(不再是一些standart命令)对我有效

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Design;
    using System.Diagnostics;
    using System.Windows.Forms;
    using System.Drawing;
    
    namespace DesignerHost
    {
        class MenuCommandServiceImpl : MenuCommandService
        {
            DesignerVerbCollection m_globalVerbs = new DesignerVerbCollection();
    
            public MenuCommandServiceImpl(IServiceProvider serviceProvider)
                : base(serviceProvider)
            {
                m_globalVerbs.Add(StandartVerb("Cut", StandardCommands.Cut));
                m_globalVerbs.Add(StandartVerb("Copy", StandardCommands.Copy));
                m_globalVerbs.Add(StandartVerb("Paste", StandardCommands.Paste));
                m_globalVerbs.Add(StandartVerb("Delete", StandardCommands.Delete));
                m_globalVerbs.Add(StandartVerb("Select All", StandardCommands.SelectAll));
    
            }
    
            private DesignerVerb StandartVerb(string text, CommandID commandID)
            {
                return new DesignerVerb(text,
                    delegate(object o, EventArgs e) 
                    {
                        IMenuCommandService ms = 
                            GetService(typeof(IMenuCommandService)) as IMenuCommandService;
                        Debug.Assert(ms != null);
                        ms.GlobalInvoke(commandID); 
                    }
                );
            }
    
            class MenuItem : ToolStripMenuItem
            {
                DesignerVerb verb;
    
                public MenuItem(DesignerVerb verb)
                    : base(verb.Text)
                {
                    Enabled = verb.Enabled;
                    this.verb = verb;
                    Click += InvokeCommand;
                }
    
                void InvokeCommand(object sender, EventArgs e)
                {
                    try
                    {
                        verb.Invoke();
                    }
                    catch (Exception ex)
                    {
                        Trace.Write("MenuCommandServiceImpl: " + ex.ToString());
                    }
                }
            }
    
            private ToolStripItem[] BuildMenuItems()
            {
                List<ToolStripItem> items = new List<ToolStripItem>();
    
                foreach (DesignerVerb verb in m_globalVerbs) 
                {
                    items.Add(new MenuItem(verb));
                }
                return items.ToArray();
            }
    
            #region IMenuCommandService Members
    
            /// This is called whenever the user right-clicks on a designer.
            public override void ShowContextMenu(CommandID menuID, int x, int y)
            {
                // Display our ContextMenu! Note that the coordinate parameters to this method
                // are in screen coordinates, so we've got to translate them into client coordinates.
    
                ContextMenuStrip cm = new ContextMenuStrip();
                cm.Items.AddRange(BuildMenuItems());
    
                ISelectionService ss = GetService(typeof (ISelectionService)) as ISelectionService;
                Debug.Assert(ss != null);
    
                Control ps = ss.PrimarySelection as Control;
                Debug.Assert(ps != null);
    
                Point s = ps.PointToScreen(new Point(0, 0));
                cm.Show(ps, new Point(x - s.X, y - s.Y));
            }
    
            #endregion
    
        }
    }
    

    更新

    建立 similar solution

        2
  •  1
  •   this. __curious_geek    15 年前

    一个月前我遇到了同样的问题,从codeplex得到了一些非常有趣和有用的东西。 here . 我在上读到的 Brad Abram's Blog 邮政。其中包括许多关于框架扩展性的例子,自定义windows窗体设计器界面就是其中之一。

    链接TXT 1: http://mef.codeplex.com/

    链接TXT 2: http://blogs.msdn.com/brada/archive/2009/04/13/managed-extensibility-framework-preview-5-released.aspx

    谢谢.