设计时间拖放

5
我目前正在参与一个项目,我的任务是设计一个设计表面,让最终用户可以在运行时添加/删除/移动控件。
我遵循了这个教程"《托管 Windows 窗体设计器》by Tim Dawson", 已经几乎实现了我所需的所有功能。

不想阅读教程的人的短篇小说:我实现了IDesignerHost, IContainer, ISelectionService, IToolboxService以及其他一些接口,来创建我的设计界面。我没有使用框架中已经存在的System.ComponentModel.Design.DesignSurface,主要是因为我需要一个非常定制化的设计界面。

问题:

我希望允许用户从IToolboxService拖放新的控件到IDesignerHost/IContainer中。在本教程中,您可以在工具箱中单击一个控件,然后单击设计表面以添加该控件。

我找到的内容:

  • 有一个内置功能可以自动从IToolboxService拖放到System.ComponentModel.Design.DesignSurface,但如果您从头实现IDesignerHost,则明显无法工作。
  • 当您使用Control.DoDragDrop(ToolboxItem)方法启动拖放时:

    1. 调用IToolboxService.SerializeToolboxItem(ToolboxItem)对项进行序列化
    2. 调用IToolboxService.IsToolboxItem(object)
      IToolboxService.IsSupported(object)以评估是否可以允许将序列化的ToolboxItem删除在设计表面上
    3. 当您放下控件时:IToolboxService.DeserializeToolboxItem(object serializedObject)由设计表面调用以反序列化已删除的控件。
  • 调用IToolboxService.SetCursor()以了解是否定义了自定义光标,还是使用标准Windows光标。

问题:

我已经按照上述所有内容进行了实现,在"What i've found"中,但是拖放功能存在一些问题:
  • 我拖动时一切正常,但当悬停在设计表面上时,我的光标会在标准光标和"DragDropEffects.Copy"样式之间闪烁。
  • 当我放下时,什么也不会发生,当我的光标离开设计表面(放下后),新的Control就会被创建并添加到我放下的位置。

是否有人尝试过我正在做的事情?如果是这样,你是如何处理的? 是否有任何指针/链接/好建议可以提供?

谢谢=)


你好,你解决了鼠标闪烁的问题吗?我也在使用同一个设计工具,遇到了鼠标指针闪烁的问题。例如,当我想从工具箱中拖动控件到面板上时,面板会闪烁。 - Zhyke
2个回答

3
有人有相关的指针/链接/建议吗? 您的问题似乎可以在Microsoft Connect问题Mouse Events Consumed / Not Raised in 2.0 Designers中找到解决方法。尽管这个问题并不容易理解,但显然从.NET Framework 1.1(2003)升级到2.0(2006)意味着拖放行为的改变——鉴于您提到的文章来自2003年,这可能与此有关。具体而言,您应该滚动到第2个问题部分,引用如下:

"当你在窗体上拖动时,你会注意到持续的闪烁。这在2.0中部分是由新的拖放行为引起的。"

我现在无法深入研究,但您也可以从Customize Drag & Drop in the Designer中找到一些线索,其中包括有关Visual Studio版本2003和2005之间拖放行为的更改;很可能这也与您的问题有关,事实上,其中一个被接受的答案确实专门提到了上述Microsoft Connect问题,还提供了更多的可能解决方案。

天哪,他们改变行为了吗?我要看一下你的链接,它们似乎与我的问题非常相关,特别是微软连接,因为他们使用了我用来设计我的设计器的相同解决方案/教程。谢谢你。 - Clement Herreman

0

我在一天前就开始研究这个问题了。这是我为类似于你的项目找到的解决方案。

  1. 我拖动时一切正常,但当悬停在设计表面上时,我的光标会在标准光标和“DragDropEffects.Copy”样式之间闪烁。

这是我的工具箱服务。

class EasyAccordionToolboxService : AccordionControl, IToolboxService
{
    EasyAccordionControlElement _SelectedElement;
    public Control DesignPanel { get; set; }

    public EasyAccordionToolboxService()
    {
        AddAccordions();
        AllowItemSelection = true;
        base.ElementClick += EasyAccordionToolboxService_ElementClick;
    }

    private void EasyAccordionToolboxService_ElementClick(object sender, ElementClickEventArgs e)
    {
        if (e.Element.Level == 1) this._SelectedElement = e.Element as EasyAccordionControlElement;
    }

    public ToolboxItem GetSelectedToolboxItem()
    {
        if(_SelectedElement != null)
        {
            var selectedToolboxItem = this._SelectedElement.ToolBoxItem;
            this._SelectedElement = null;
            return selectedToolboxItem;
        }
        else
        {
            return null;
        }
    }

        public bool SetCursor()
    {
        if(this._SelectedElement == null)
        {
            this.DesignPanel.Cursor = Cursors.Default;
        }
        else
        {
            this.DesignPanel.Cursor = Cursors.Hand;
        }

        return true;
    }

在编程方面,有“DesignPanel”属性和“SetCursor”方法。DesignPanel属性是指根设计器视图的控件。

  1. 当我拖放控件时,没有任何反应,只有在我的光标离开设计表面后(在我拖放后),新的控件才会被创建并添加到我拖放的位置。

从IToolboxService实现的EasyAccordionToolBoxService中有GetSelectedToolboxItem方法。GetSelectedToolboxItem就是你要找的答案。

最后,

        designer = new EasyDesignSurface(propertyGrid);

        var rootForm = (Form)designer.CreateComponent(typeof(Form));
        rootForm.Name = "rootForm";
        rootForm.Text = "BELGE";
        rootForm.TopLevel = false;
        rootForm.Size = new Size(600, 600);
        designer.ComponentContainer.Add(rootForm);

        var view = (Control)designer.View;
        view.Dock = DockStyle.Fill;
        designPanel.Controls.Add(view);

        easyAccordionToolboxService1.DesignPanel = view;
        designer.AddService(typeof(IToolboxService), easyAccordionToolboxService1);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接