【问题标题】:.NET custom form designer: How to implement IMenuCommandService?.NET 自定义表单设计器:如何实现 IMenuCommandService?
【发布时间】:2010-10-27 16:38:37
【问题描述】:

我有一个很久以前为数据库项目编写的报表设计器。它使用了很多 winapi 魔法,因此我不得不“以正确的方式”重写一些部分。

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

  1. 到目前为止,我在该主题上发现的每个资源都有些过时了。你能指出新鲜/全面的文章吗?

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

    MenuCommandService.ShowContextMenu 被调用,但没有出现,因为 globalVerbs 集合中没有任何 DesignerVerbs。我是否应该手动添加与剪切/粘贴等设计器操作相对应的“标准”操作?如果是,我该怎么做?

【问题讨论】:

  • 我在这方面从未见过任何好的文档。有关为控件创建设计器的信息,是的,但不是整个表单。我建议你花时间用 Reflector 查看源代码,或者共享源代码。

标签: c# winforms .net-2.0 form-designer


【解决方案1】:

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

链接文本 1:http://mef.codeplex.com/

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

谢谢。

【讨论】:

【解决方案2】:

感谢 SharpDevelop 资源,我能够找到解决方案

这个最小的实现(一些标准命令,不再)对我有用

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

【讨论】:

  • 我知道迟到了,但在“类似解决方案”中存在问题。在那里,如果您单击菜单,它会使用 GlobalInvoke(designerVerb.CommandID) 调用动词。有些动词共享相同的 CommandID(即从 TabStrip 中添加和删除选项卡,因此类似的解决方案并非在每种情况下都有效。在这里,在单击菜单时,使用可以正常工作的 DesignerVerb.Invoke() 调用要执行的操作.
猜你喜欢
  • 1970-01-01
  • 2011-11-13
  • 2010-10-19
  • 2010-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-05
相关资源
最近更新 更多