5
votes

I'm currently working of a project where my part is to design a Design Surface where the end user can add/remove/move controls at run-time.

I followed this tutorial "Hosting Windows Forms Designers, by Tim Dawson", and almost have implemented all the features I need.

Short story for those who don't want to read the tutorial : I implemented IDesignerHost, IContainer, ISelectionService, IToolboxService and some other interface, to create my design surface. I didn't use the System.ComponentModel.Design.DesignSurface already in the framework, mainly beacause I need a really custom design surface.

Question :

I want to allow user to drag & drop new Control from the IToolboxService to the IDesignerHost/IContainer. In this tutorial, you clic on a Control in the toolbox, the click on the design surface to add the control.

What i've found :

  • There is a built-in feature that automagically does drag & drop from IToolboxService to System.ComponentModel.Design.DesignSurface but it is clearly not working if you implement IDesignerHost from nothing.
  • When you use the Control.DoDragDrop(ToolboxItem) method, to initiate a drag & drop :

    1. IToolboxService.SerializeToolboxItem(ToolboxItem) is called to serialize the item
    2. IToolboxService.IsToolboxItem(object) and
      IToolboxService.IsSupported(object) are called to evaluate if the
      serialized ToolboxItem can be allowed to be droped on the design surface
    3. When you drop the control : IToolboxService.DeserializeToolboxItem(object serializedObject) is called by the design surface to deserialize the controldropped.
  • IToolboxService.SetCursor() is called to know if you define a custom cursor, or let the standard windows cursor.

Problem :

I implemented all mentionned above, in the "What i've found", but the drag & drop is buggy :

  • I drag, everything's fine, but when hovering the design surface, my cursor blink a little between standard cursor and the "DragDropEffects.Copy" style.
  • When I drop, nothing happens, and when my cursor leave the design surface (after I dropped), then the new Control is created and added where I dropped it.

Has anyone ever tried to do what I'm doing, and if so, how did you manage it ? Is there anyone that has any pointer/link/good advices ?

Thank you =)

2
Hi, did you resolve the issue on mouse blinking? I am also working on the same Designer and i am encountering the mouse point blinking and for example i want to drag the control from the toolbox to the Panel, the panel is flickering.Zhyke

2 Answers

3
votes

Is there anyone that has any pointer/link/good advices?

Your issue seems to be addressed by the Microsoft Connect issue Mouse Events Consumed / Not Raised in 2.0 Designers. This issue is all but easy to grasp though, but apparently the upgrade from .NET Framework 1.1 (2003) to 2.0 (2006) implied a change in drag & drop behavior - given that the article you mentioned stems from 2003 this could well be related. Specifically you should scroll ahead to section Issue 2, citation:

You will now notice constant flickering when dragging over the form. This is partially caused by the new drag-drop behavior in 2.0.

I'm unable to dig deeper into this right now myself but you might also be able to figure something from Customize Drag & Drop in the Designer, which addresses changed behavior regarding drag & drop between Visual Studio versions 2003 and 2005; quite likely this might be related and one of the accepted answers does in fact specifically reference the Microsoft Connect issue above, plus it offers more hints towards possible solutions too.

0
votes

Me to worked on this questions for one day ago. This is my solution that found for my project like yours.

  1. I drag, everything's fine, but when hovering the design surface, my cursor blink a little between standard cursor and the "DragDropEffects.Copy" style.

This is my toolboxservice.

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;
    }

There are "DesignPanel" property and "SetCursor" methods. DesignPanel property is control referred to view of root designer.

  1. When I drop, nothing happens, and when my cursor leave the design surface (after I dropped), then the new Control is created and added where I dropped it.

There is GetSelectedToolboxItem method in EasyAccordionToolBoxService implemented from IToolboxService. GetSelectedToolboxItem is your answer.

Finally,

        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);