【问题标题】:Is is possible to detect Undo/Redo in a Powerpoint Addin via C#?是否可以通过 C# 在 Powerpoint 插件中检测撤消/重做?
【发布时间】:2012-11-05 13:56:34
【问题描述】:

是否可以通过 C# 在 Powerpoint 插件中检测撤消/重做事件?或者是否可以访问已发生的事情或操作撤消/重做列表?

我问是因为我没有看到任何允许这样做的东西,这让我感到惊讶,我期待它是可能的,所以我问的主要是希望我错过了什么。

任何帮助将不胜感激!

【问题讨论】:

    标签: c# add-in powerpoint undo undo-redo


    【解决方案1】:

    很遗憾,PPT 没有公开撤消列表,并且没有可以捕获的事件来让您知道撤消/重做何时发生。

    我想有可能实现您自己的撤消堆栈,但这似乎是斯蒂芬金会写小说的那种东西。 ;-)

    【讨论】:

    • 叹息,我希望不是这样...感谢@Steve 提供的信息...
    • 现在基于 Web 的新插件的 API 限制更加荒谬,是时候阻止任何尝试构建 PPT 插件的人了。
    • @SoonDead 为什么? VBA 仍然有效,COM 仍然有效。仅仅因为 MS 引入了一个几乎无用的新 API,并不意味着当有更好的、经过验证的技术可用时,任何人都需要使用它。
    • 是的,这是真的。我的观点是 VSTO 的 API 非常古怪,并且缺少有用的功能(例如获取幻灯片的缩略图、查找幻灯片是否已更改,甚至始终查找用户实际看到的幻灯片)。 MS 并没有将这些改造成更愉快的 API 体验,而是发布了一个荒谬的 JavaScript API。
    【解决方案2】:

    我也在寻找 Ctrl+Z/Undo 的事件。 Undo 功能的 idMso 控件是一个库,因此就通过 customUI 中的 a 重新调整用途而言,这是一个死胡同。没有内置的 Application.OnUndo 事件,我唯一能想到的另一件事是使用 WinAPI 连接到 PowerPoint 的 WindowProc 过程以检测 Ctrl+Z。我简单地尝试了一下,可以检测到该组合键,但我鄙视这种事情导致的不稳定性,导致 PowerPoint 在某些系统上可能崩溃,并且无法解决 macOS。如果有人想改进它,这里是该技术的基础:

    Option Explicit
    
    Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As Any, ByVal lpWindowName As Any) As LongPtr
    Private Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
    Private Declare PtrSafe Function RegisterHotKey Lib "user32" (ByVal hwnd As LongPtr, ByVal ID As Long, ByVal fsModifiers As Long, ByVal vk As Long) As Long
    Private Declare PtrSafe Function UnregisterHotKey Lib "user32" (ByVal hwnd As LongPtr, ByVal ID As Long) As Long
    
    Private Declare PtrSafe Function CallWindowProc Lib "user32" Alias "CallWindowProcA" ( _
                                            ByVal lpPrevWndFunc As LongPtr, _
                                            ByVal hwnd As LongPtr, _
                                            ByVal MSG As Long, _
                                            ByVal wParam As LongPtr, _
                                            ByVal lParam As LongPtr) As LongPtr
    Public hWndPPT As LongPtr
    
    Public Type POINTAPI
      x As Long
      y As Long
    End Type
    
    Public Type MSG
        hwnd As LongPtr
        Message As Long
        wParam As LongPtr
        lParam As LongPtr
        time As Long
        PT As POINTAPI
    End Type
    
    #If Win64 Then
       Private Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
    #Else
       Private Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
    #End If
    
    Private Const GWL_WNDPROC As Long = -4& ' Sets a new address for the window procedure
    
    Private PrevWndFunc As LongPtr          ' Pointer to the initial window proc
    
    Private Const WM_HOTKEY = &H312&        ' HotKey message
    
    Private Const MOD_Control = 2           ' Either CTRL key
    
    Public Sub RegisterCtrlZ()
        
        Dim returnedVal
        
        hWndPPT = GetPPThWnd
        
        returnedVal = RegisterHotKey(hwnd:=hWndPPT, ID:=1, fsModifiers:=MOD_Control, vk:=vbKeyZ)
        Debug.Print "RegisterHotKey returned " & returnedVal
    
        ' Set the window callback procedure
        PrevWndFunc = SetWindowLongPtr(hWndPPT, GWL_WNDPROC, AddressOf WindowProc)
    
    End Sub
    
    Public Sub UnregisterCtrlZ()
        
        Dim returnedVal
    
        hWndPPT = GetPPThWnd
        
        returnedVal = UnregisterHotKey(hwnd:=hWndPPT, ID:=1)
        Debug.Print "UnregisterHotKey returned " & returnedVal
        
        PrevWndFunc = SetWindowLongPtr(hWndPPT, GWL_WNDPROC, PrevWndFunc)
        
    End Sub
    
    Public Function WindowProc(ByVal hwnd As LongPtr, ByVal uMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
    
        ' Check if a hotkey and the main PPT window is the active window
        If uMsg = WM_HOTKEY And GetActiveWindow = hWndPPT Then
            Debug.Print "Hotkey " & wParam & " event (Ctrl+Z)"
        End If
        
        ' Call the next window proc
        WindowProc = CallWindowProc(PrevWndFunc, hwnd, uMsg, wParam, lParam)
        
    End Function
    
    ' Get the handle for the PowerPoint window
    Public Function GetPPThWnd() As LongPtr
    
        Select Case Val(Application.Version)
            Case 8
                GetPPThWnd = FindWindow("PP97FrameClass", 0&)
            Case 9 To 12
                GetPPThWnd = FindWindow("PP" & Val(Application.Version) & "FrameClass", 0&)
            Case Else
                GetPPThWnd = FindWindow("PPTFrameClass", vbNullString)
        End Select
        
    End Function
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-16
      • 2020-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-20
      相关资源
      最近更新 更多