是否可以通过 C# 在 Powerpoint 插件中检测撤消/重做事件?或者是否可以访问已发生的事情或操纵撤消/重做列表?
我问是因为我没有看到任何允许这样做的东西,这让我感到惊讶,我期待它是可能的,所以我问主要是希望我错过了什么。
任何帮助将非常感激!
是否可以通过 C# 在 Powerpoint 插件中检测撤消/重做事件?或者是否可以访问已发生的事情或操纵撤消/重做列表?
我问是因为我没有看到任何允许这样做的东西,这让我感到惊讶,我期待它是可能的,所以我问主要是希望我错过了什么。
任何帮助将非常感激!
遗憾的是,PPT 没有公开撤消列表,并且没有可以捕获的事件来让您知道撤消/重做何时发生。
我想可以实现自己的撤消堆栈,但这似乎是斯蒂芬金写小说的那种东西。;-)
我也在寻找 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