【问题标题】:How to invoke an action during powerpoint slideshow programmatically?如何以编程方式在 powerpoint 幻灯片放映期间调用操作?
【发布时间】:2012-01-03 12:28:57
【问题描述】:

我正在使用 Coded UI 和 VSTO 自动化 Powerpoint 场景。在我的 powerpoint 演示文稿中,我在形状上创建了一个“操作”设置来启动记事本。在幻灯片放映期间,我需要通过单击“文本/形状”来调用此操作,以便它打开 notepad.exe。谁能帮助我如何实现这一目标。我写了以下代码。

//To launch Powepoint
PowerPoint.Application objPPT = new PowerPoint.Application();
objPPT.Visible = Office.MsoTriState.msoTrue;

//Add new presentation
PowerPoint.Presentations oPresSet = objPPT.Presentations;
PowerPoint.Presentation oPres = oPresSet.Add(Office.MsoTriState.msoTrue);

//Add a slide
 PowerPoint.Slides oSlides = oPres.Slides;
PowerPoint.Slide oSlide = oSlides.Add(1, PowerPoint.PpSlideLayout.ppLayoutTitleOnly);

//Add text
 PowerPoint.TextRange tr = oSlide.Shapes[1].TextFrame.TextRange;
tr.Text = "Launch notepad";
tr.Select();

//Add Action settings on the shape
oSlide.Shapes[1].ActionSettings[PowerPoint.PpMouseActivation.ppMouseClick].Action = PowerPoint.PpActionType.ppActionRunProgram;
oSlide.Shapes[1].ActionSettings[PowerPoint.PpMouseActivation.ppMouseClick].Run = "c:\\windows\\notepad.exe";

//start slideshow
objPPT.ActivePresentation.SlideShowSettings.Run();

这将启动演示文稿的幻灯片放映,并显示第一张幻灯片“在形状上定义动作设置的位置”。现在如何通过 API 自动启动 notepad.exe?不幸的是,编码的 UI 无法检测幻灯片中的对象。因此,可能无法使用 UI 鼠标单击选项。

[编辑] 能够取得一点点进步。我在幻灯片放映期间得到了形状对象。这是对上述代码的扩展。

PowerPoint.SlideShowWindow oSsWnd = objPPT.ActivePresentation.SlideShowWindow;
PowerPoint.Shape oShape = oSsWnd.View.Slide.Shapes[1];

【问题讨论】:

  • 我不清楚你想要完成什么。如果要创建演示文稿,在幻灯片放映视图中启动它,然后启动记事本,为什么要通过 PowerPoint 来创建?创建并启动 PPT 节目后,让您的代码启动记事本。
  • 这是一个自动化场景,用于验证操作是否正常工作。因此我只能这样做
  • 我明白了。我不知道有什么方法可以自动点击屏幕上的任何特定形状或点。
  • 如果您只想在运行命令正确的情况下发短信,您可以枚举该形状和Shell(ActionSettings[Click].Run) if Action = ppActionRunProgram
  • Paul B,我不知道如何在这里使用 Shell 函数。我能否进一步详细说明。

标签: c# vba vsto powerpoint


【解决方案1】:

不要问我为什么 C# 会这样,但确实如此!

您必须发出两次命令才能使其工作...

    private void button1_Click(object sender, EventArgs e)
    {
        //To launch Powepoint
        PowerPoint.Application objPPT = new PowerPoint.Application();
        objPPT.Visible = Microsoft.Office.Core.MsoTriState.msoTrue;

        //Add new presentation
        PowerPoint.Presentations oPresSet = objPPT.Presentations;
        PowerPoint.Presentation oPres = oPresSet.Add(Microsoft.Office.Core.MsoTriState.msoTrue);

        //Add a slide
        PowerPoint.Slides oSlides = oPres.Slides;
        PowerPoint.Slide oSlide = oSlides.Add(1, PowerPoint.PpSlideLayout.ppLayoutTitleOnly);

        //Add text
        PowerPoint.TextRange tr = oSlide.Shapes[1].TextFrame.TextRange;
        tr.Text = "Launch notepad";
        //tr.Select();

        //Add Action settings on the shape
        oSlide.Shapes[1].ActionSettings[PowerPoint.PpMouseActivation.ppMouseClick].Action = PowerPoint.PpActionType.ppActionRunProgram;
        oSlide.Shapes[1].ActionSettings[PowerPoint.PpMouseActivation.ppMouseClick].Run = @"C:\WINDOWS\system32\notepad.exe";
        oSlide.Shapes[1].ActionSettings[PowerPoint.PpMouseActivation.ppMouseClick].Action = PowerPoint.PpActionType.ppActionRunProgram;
        oSlide.Shapes[1].ActionSettings[PowerPoint.PpMouseActivation.ppMouseClick].Run = @"C:\WINDOWS\system32\notepad.exe";
        //start slideshow
        objPPT.ActivePresentation.SlideShowSettings.Run();

    }

【讨论】:

  • 对不起 Siddhart.. 我正在寻找的是如何在演示文稿的幻灯片放映期间“调用”该操作。您的代码仅有助于如何在我已经知道的形状上设置操作设置。希望你能有所作为。我还在寻找答案。
【解决方案2】:

这可能是一个比您希望的解决方案更复杂的解决方案,但如果您能以某种方式确定屏幕上“文本/形状”对象的 X 和 Y 坐标(也许使用编码 UI 和 VSTO 库?) ,您可以使用 User32 "SendInput" 方法来模拟将鼠标移动到对象的位置,然后模拟鼠标单击。

这是模拟用户输入的代码:

int x, y;
// ...  First obtain the X and Y coordinate of the "text/shape" object from APIs

//
InputEmulator inputEmulator = new InputEmulator();
inputEmulator.MoveMouse(x, y);
inputEmulator.ClickMouse();

这里是一个 InputEmulator 类的精简版,我用它来模拟 Windows UI 操作:

class InputEmulator
{
    private const int INPUT_MOUSE = 0;
    private const uint MOUSEEVENTF_MOVE = 0x0001;
    private const uint MOUSEEVENTF_ABSOLUTE = 0x8000;
    private const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
    private const uint MOUSEEVENTF_LEFTUP = 0x0004;

    public void MoveMouse(int x, int y)
    {
        INPUT[] inp = new INPUT[1];
        inp[0].type = INPUT_MOUSE;
        inp[0].mi = createMouseInput(x, y, 0, 0, MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE);


        SendInput((uint)1, inp, Marshal.SizeOf(inp[0].GetType()));
    }

    public void ClickMouse()
    {
        INPUT[] inp = new INPUT[2];
        inp[0].type = INPUT_MOUSE;
        inp[0].mi = createMouseInput(0, 0, 0, 0, MOUSEEVENTF_LEFTDOWN);
        inp[1].type = INPUT_MOUSE;
        inp[1].mi = createMouseInput(0, 0, 0, 0, MOUSEEVENTF_LEFTUP);
        SendInput((uint)inp.Length, inp, Marshal.SizeOf(inp[0].GetType()));
    }

    [DllImport("user32.dll", SetLastError = true)]
    private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

    private static MOUSEINPUT createMouseInput(int x, int y, uint data, uint t, uint flag)
    {
        MOUSEINPUT mi = new MOUSEINPUT();
        mi.dx = x;
        mi.dy = y;
        mi.mouseData = data;
        mi.time = t;
        //mi.dwFlags = MOUSEEVENTF_ABSOLUTE| MOUSEEVENTF_MOVE;
        mi.dwFlags = flag;
        return mi;
    }

    [StructLayout(LayoutKind.Explicit)]
    private struct INPUT
    {
        [FieldOffset(0)]
        public int type;
        [FieldOffset(sizeof(int))] //[FieldOffset(8)] for x64
        public MOUSEINPUT mi;
    }

    [StructLayout(LayoutKind.Sequential)]
    struct MOUSEINPUT
    {
        public int dx;
        public int dy;
        public uint mouseData;
        public uint dwFlags;
        public uint time;
        public IntPtr dwExtraInfo;
    }
}

【讨论】:

  • 谢谢 nomizzz。看起来很有希望。一旦我对基于 SDK 的解决方案的搜索变得徒劳,我将尝试实现这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-14
  • 1970-01-01
  • 1970-01-01
  • 2022-11-18
  • 2012-12-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多