After calling DoDragDrop
with a String.Empty
first parameter, it is possible to get the current cursor coordinates.
Getting the coordinates needs some Win32 boilerplate:
[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;
}
Then these coordinates have to be converted into the slide's coordinate system (the slide has a different size in points than how it appears on the screen in pixels).
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);