none
How to drag&drop multiple shapes with a PowerPoint (2010 or 2013) add-in? RRS feed

  • Question

  • I would like to implement a PowerPoint add-in with a custom task pane from which the users can drag complex objects objects onto the slide (these objects would consist of multiple shapes, for instance two triangles in a circle or something like that).

    I managed to achieve dropping simple text boxes onto slides by calling DoDragDrop in a user control and passing the desired text as the method's first parameter. However I don't know if it's possible to pass a more copmlex object like multiple shapes as the data parameter of the DoDragDrop method.

    The other approach I tried is to call DoDragDrop with an empty string (that way nothing gets dropped onto the slide), and after DoDragDrop returned I can add shapes to the slide using the Globals.ThisAddIn.Application.ActiveWindow.View.Slide.AddShape method, however I couldn't find a way to get the current position of the mouse pointer.

    So is it somehow possible to call DoDragDrop and pass multiple shapes to it, or get the cursor position after DoDragDrop returned?

    Thursday, April 24, 2014 2:25 PM

Answers

  • Hi Mark,

    >> So the question is that is the same thing possible in PowerPoint 2010?

    I’m afraid there are no Drop & Drag events in Power Point 2010. Application.AfterDragDropOnSlide Event is added in PowerPoint 2013.

    To get the cursor position, you could try to use the code below:

        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            public int X;
            public int Y;
    
            public POINT(int x, int y)
            {
                this.X = x;
                this.Y = y;
            }
        }
    
        class Win32API
        {
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
    
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool GetCursorPos(out POINT lpPoint);
        }
    
    
            private void GetCursorPosButton_Click(object sender, EventArgs e)
            {
                POINT point = new POINT();
    
                Win32API.GetCursorPos(out point);
    
                Win32API.ScreenToClient(new IntPtr(Globals.ThisAddIn.Application.ActiveWindow.HWND), ref point);
            }

    Hope it will help.

    Regards,

    Jeffrey


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Mark Vincze Monday, May 5, 2014 2:22 PM
    Thursday, May 1, 2014 7:29 AM
    Moderator
  • Thanks for the info!

    I managed to achieve my goal using this, the screen coordinates had to be converted into the slide's point coordinate system:

    private POINT ConvertScreenPointToSlideCoordinates(POINT point)
    {
    	// Get the screen coordinates of the upper-left hand corner of the slide.
    	POINT refPointUpperLeft = new POINT(
    		Globals.ThisAddIn.Application.ActiveWindow.PointsToScreenPixelsX(0),
    		Globals.ThisAddIn.Application.ActiveWindow.PointsToScreenPixelsY(0));
    
    	// Get the size of the slide (in points of the slide's coordinate system).
    	var slide = Globals.ThisAddIn.Application.ActiveWindow.View.Slide;
    	var slideWidth = slide.CustomLayout.Width;
    	var slideHeight = slide.CustomLayout.Height;
    
    	// Get the screen coordinates of the bottom-right hand corner of the slide.
    	POINT refPointBottomRight = new POINT(
    		Globals.ThisAddIn.Application.ActiveWindow.PointsToScreenPixelsX(slideWidth),
    		Globals.ThisAddIn.Application.ActiveWindow.PointsToScreenPixelsY(slideHeight));
    
    	// Both reference points have to be converted to the PowerPoint window's coordinate system.
    	Win32API.ScreenToClient(new IntPtr(Globals.ThisAddIn.Application.ActiveWindow.HWND), ref refPointUpperLeft);
    	Win32API.ScreenToClient(new IntPtr(Globals.ThisAddIn.Application.ActiveWindow.HWND), ref refPointBottomRight);
    
    	// Convert the point to the slide's coordinate system (convert the pixel coordinate inside the slide into a 0..1 interval, then scale it up by the slide's point size).
    	return new POINT(
    		(int)Math.Round((double)(point.X - refPointUpperLeft.X) / (refPointBottomRight.X - refPointUpperLeft.X) * slideWidth),
    		(int)Math.Round((double)(point.Y - refPointUpperLeft.Y) / (refPointBottomRight.Y - refPointUpperLeft.Y) * slideHeight));
    }
    The code doing the drag&drop:
    DoDragDrop(String.Empty, DragDropEffects.Copy);
    
    var point = GetCursorPosition();
    var convertedPoint = this.ConvertScreenPointToSlideCoordinates(point);
    
    // Insert something at the cursor's location:
    var slide = Globals.ThisAddIn.Application.ActiveWindow.View.Slide;
    slide.Shapes.AddShape(Microsoft.Office.Core.MsoAutoShapeType.msoShapeCloud, convertedPoint.X, convertedPoint.Y, 100, 100);


    • Marked as answer by Mark Vincze Monday, May 5, 2014 2:22 PM
    • Edited by Mark Vincze Monday, May 5, 2014 2:24 PM
    Monday, May 5, 2014 2:22 PM

All replies

  • Currently, looks like we can't do it in PPT APP now, please refer this: http://msdn.microsoft.com/en-us/library/office/fp142185(v=office.1501401).aspx

    In my experience, I suggest you using VSTO.


    You have Failed this City:)

    Friday, April 25, 2014 9:59 AM
  • Umm, I would like to develop the add-in with Visual Studio in C#, that's VSTO, isn't it?
    Friday, April 25, 2014 1:49 PM
  • Yes.

    For more information, please refer to:

    Create Add-ins and Customizations for Office by using Visual Studio


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Monday, April 28, 2014 3:16 AM
    Moderator
  • Thanks for the link, however I have already studied the documentation quite a lot.

    I have a very specific question in my opening post,  and I would like to get some advice on that, possibly from someone who already has experience with that problem.

    Monday, April 28, 2014 12:21 PM
  • I found a solution for PowerPoint 2013, it can be done with the new AfterDragDropOnSlide event (it's not trivial though, details here: http://social.msdn.microsoft.com/Forums/en-US/724f1737-afa5-4762-8740-5b3745e06f8a/afterdragdroponslide-event-in-ppt-2013?forum=isvvba).

    So the question is that is the same thing possible in PowerPoint 2010?

    Monday, April 28, 2014 2:48 PM
  • It depend on where you want to put drag & drop.

    From my opinion, if it can be done in a windows form application, it also can be done in the user control of a task pane. It is related to which control you need to drag & drop.

    Have a look at Control.DoDragDrop Method.

    Tuesday, April 29, 2014 10:18 AM
  • I am already using DoDragDrop method, I described the details in the first post.

    I would like to drop from the custom task pane to a slide, and I managed to achieve that in PP 2013, but not in 2010 because of the lack of the AfterDragDropOnSlide event.

    Tuesday, April 29, 2014 10:47 AM
  • Hi Mark,

    >> So the question is that is the same thing possible in PowerPoint 2010?

    I’m afraid there are no Drop & Drag events in Power Point 2010. Application.AfterDragDropOnSlide Event is added in PowerPoint 2013.

    To get the cursor position, you could try to use the code below:

        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            public int X;
            public int Y;
    
            public POINT(int x, int y)
            {
                this.X = x;
                this.Y = y;
            }
        }
    
        class Win32API
        {
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
    
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool GetCursorPos(out POINT lpPoint);
        }
    
    
            private void GetCursorPosButton_Click(object sender, EventArgs e)
            {
                POINT point = new POINT();
    
                Win32API.GetCursorPos(out point);
    
                Win32API.ScreenToClient(new IntPtr(Globals.ThisAddIn.Application.ActiveWindow.HWND), ref point);
            }

    Hope it will help.

    Regards,

    Jeffrey


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Mark Vincze Monday, May 5, 2014 2:22 PM
    Thursday, May 1, 2014 7:29 AM
    Moderator
  • Thanks for the info!

    I managed to achieve my goal using this, the screen coordinates had to be converted into the slide's point coordinate system:

    private POINT ConvertScreenPointToSlideCoordinates(POINT point)
    {
    	// Get the screen coordinates of the upper-left hand corner of the slide.
    	POINT refPointUpperLeft = new POINT(
    		Globals.ThisAddIn.Application.ActiveWindow.PointsToScreenPixelsX(0),
    		Globals.ThisAddIn.Application.ActiveWindow.PointsToScreenPixelsY(0));
    
    	// Get the size of the slide (in points of the slide's coordinate system).
    	var slide = Globals.ThisAddIn.Application.ActiveWindow.View.Slide;
    	var slideWidth = slide.CustomLayout.Width;
    	var slideHeight = slide.CustomLayout.Height;
    
    	// Get the screen coordinates of the bottom-right hand corner of the slide.
    	POINT refPointBottomRight = new POINT(
    		Globals.ThisAddIn.Application.ActiveWindow.PointsToScreenPixelsX(slideWidth),
    		Globals.ThisAddIn.Application.ActiveWindow.PointsToScreenPixelsY(slideHeight));
    
    	// Both reference points have to be converted to the PowerPoint window's coordinate system.
    	Win32API.ScreenToClient(new IntPtr(Globals.ThisAddIn.Application.ActiveWindow.HWND), ref refPointUpperLeft);
    	Win32API.ScreenToClient(new IntPtr(Globals.ThisAddIn.Application.ActiveWindow.HWND), ref refPointBottomRight);
    
    	// Convert the point to the slide's coordinate system (convert the pixel coordinate inside the slide into a 0..1 interval, then scale it up by the slide's point size).
    	return new POINT(
    		(int)Math.Round((double)(point.X - refPointUpperLeft.X) / (refPointBottomRight.X - refPointUpperLeft.X) * slideWidth),
    		(int)Math.Round((double)(point.Y - refPointUpperLeft.Y) / (refPointBottomRight.Y - refPointUpperLeft.Y) * slideHeight));
    }
    The code doing the drag&drop:
    DoDragDrop(String.Empty, DragDropEffects.Copy);
    
    var point = GetCursorPosition();
    var convertedPoint = this.ConvertScreenPointToSlideCoordinates(point);
    
    // Insert something at the cursor's location:
    var slide = Globals.ThisAddIn.Application.ActiveWindow.View.Slide;
    slide.Shapes.AddShape(Microsoft.Office.Core.MsoAutoShapeType.msoShapeCloud, convertedPoint.X, convertedPoint.Y, 100, 100);


    • Marked as answer by Mark Vincze Monday, May 5, 2014 2:22 PM
    • Edited by Mark Vincze Monday, May 5, 2014 2:24 PM
    Monday, May 5, 2014 2:22 PM