如何使用PowerPoint(2010或2013)加载项拖放多个形状?

时间:2014-04-24 14:08:56

标签: c# powerpoint office-interop office-addins

我想实现一个带有自定义任务窗格的PowerPoint加载项,用户可以从中将复杂对象拖动到幻灯片上(这些对象将包含多个形状,例如圆形中的两个三角形或类似的东西)。

我设法通过在用户控件中调用DoDragDrop并将所需文本作为方法的第一个参数传递,将简单文本框放到幻灯片上。但是我不知道是否可以将更多copmlex对象作为DoDragDrop方法的数据参数传递给多个形状。

我尝试的另一种方法是使用空字符串调用DoDragDrop(这样就不会将任何内容放到幻灯片上),并且在DoDragDrop返回后我可以使用{{{}添加形状到幻灯片1}}方法,但我找不到获取鼠标指针当前位置的方法。

那么以某种方式可以调用DoDragDrop并将多个形状传递给它,或者在DoDragDrop返回后获取光标位置吗?

更新:我找到了PowerPoint 2013的解决方案,可以使用新的Globals.ThisAddIn.Application.ActiveWindow.View.Slide.AddShape事件完成(但这不是一件容易的事,详情请参阅:http://social.msdn.microsoft.com/Forums/en-US/724f1737-afa5-4762-8740-5b3745e06f8a/afterdragdroponslide-event-in-ppt-2013?forum=isvvba)。< / p>

所以问题是PowerPoint 2010中可能存在同样的问题吗?

1 个答案:

答案 0 :(得分:3)

使用DoDragDrop第一个参数调用String.Empty后,可以获取当前光标坐标。
获取坐标需要一些Win32样板:

[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 POINT GetCursorPosition()
{
    POINT point = new POINT();

    Win32API.GetCursorPos(out point);

    Win32API.ScreenToClient(new IntPtr(Globals.ThisAddIn.Application.ActiveWindow.HWND), ref point);

    return point;
}

然后必须将这些坐标转换为幻灯片的坐标系(幻灯片的大小与像素中屏幕上显示的大小不同)。< / p>

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

执行拖放操作的代码:

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