需求来源:公司要求对来访客户播放欢迎PPT(可能同时来几拨客户,所以设置5秒自动切换)
并且支持 前置 和 后置 播放固定幻灯片。
为了方便维护,我把所有客户的幻灯片放到一个PPT里。
但是默认的自定义播放操作比较麻烦,所以有此ahk脚本。
为了方便区分是哪页,所以是用幻灯片的备注内容来判断。
PPT文件要求:
- 前置幻灯片备注为b(意为before),后置幻灯片备注为a(意为after),其他幻灯片任意备注
- 幻灯片要自行设置自动换片时间和循环播放。见 PPT示例文件
保存以下脚本,打开PPT后,按F9,就会显示相应备注,勾选相应内容即可。
则会循环播放前置+选择的页面+后置。
;前后的幻灯片,统一放在末尾 ;备注b 表示前面(before) ;备注a 表示后面(after) #SingleInstance Force "".base.base := _String ;声明 F12::reload F9:: if !ProcessExist("POWERPNT.EXE") return ;所有备注 arrAll := getNotesAll() ;分成3类 arrMain := [] arrRes := [] arrAfter := [] for _, arr in arrAll { if (arr[2] == "b") arrRes.push(arr[1]) ;前置的直接放到 arrRes else if (arr[2] == "a") arrAfter.push(arr[1]) else arrMain.push(arr) } ;选择幻灯片 for _, v in _Gui.getArrByCheckBox(arrMain, arr=>arr[2]) arrRes.push(v) if !arrRes.length() return ;NOTE 添加固定的内容 for _, v in arrAfter arrRes.push(v) ;设置自定义播放 ppt := ComObjActive("Powerpoint.application") ;退出当前播放 try ppt.SlideShowWindows(1).view.exit ap := ppt.ActivePresentation arrA := ComObjArray(12, arrRes.length()) for _, v in arrRes arrA[A_Index-1] := ap.slides(v).SlideID nn := "tmp" ss := ap.SlideShowSettings try ss.NamedSlideShows(nn).delete ss.NamedSlideShows.add(nn, arrA) ;播放 ss.RangeType := 3 ;用名称播放 ss.SlideShowName := nn ss.AdvanceMode := 2 ;时间自动切换 ss.LoopUntilStopped := true ;无限循环 ss.run return ; 获取所有备注[幻灯片序号, 内容] getNotesAll(filterHidden:=true) { arr := [] for sl in ComObjActive("Powerpoint.application").ActivePresentation.slides { if (filterHidden && sl.SlideShowTransition.hidden) continue text := rtrim(sl.NotesPage.Shapes.Placeholders(2).TextFrame.TextRange.text, "`n") if !strlen(text) continue arr.push([A_Index, text]) } return arr } class _Gui { ;通过checkbox获取选择的内容(含顺序) ;arrs可包含多个一维 ; ["a","b","c"] ; 或 ; [[2,"a"],[1,"b"],[3,"c"]] ;funcShow(二维数组才有用) 参数是 arrs 的单项 arr getArrByCheckBox(arrs, funcShow:="", strTips:="") { if !isobject(funcShow) funcShow := x=>x saveCoord := A_CoordModeToolTip CoordMode("tooltip", "window") oGui := GuiCreate() oGui.OnEvent("escape", "doExit") oGui.OnEvent("close", "doExit") oGui.SetFont("s13 cRED") if strlen(strTips) oGui.AddText(, strTips) oGUI.AddRadio("H20 section", "全选").OnEvent("click", "selectAll") oGUI.AddRadio("H20 ys", "不选").OnEvent("click", "selectNone") oGUI.AddRadio("H20 ys", "反选").OnEvent("click", "selectReverse") ;添加核心内容 oGui.SetFont("s13 c0") arrCtl := [] idxAll := 0 this.arrIdx := [] if isobject(arrs[1]) ;二维 { for _, arr in arrs { idx := A_Index idxAll++ if (A_Index == 1) { if (idx == 1) arrCtl[idxAll] := oGui.AddCheckbox("H20 xs section",funcShow.call(arr)) ;"H20 xs checked section" else arrCtl[idxAll] := oGui.AddCheckbox("H20 ys section",funcShow.call(arr)) } else arrCtl[idxAll] := oGui.AddCheckbox("H20 xs",funcShow.call(arr)) arrCtl[idxAll].name := idxAll ;记录序号当作值 arrCtl[idxAll].OnEvent("click", "doClick") ;if (mod(idx,2) == 1) ;红黑字交替 ;oGui.SetFont("cRED") ;else ;oGui.SetFont("c0") } } else { idx := 0 for _, v in arrs { if strlen(v) { idx++ arrCtl[idx] := oGui.AddCheckbox("H20 xs",v) arrCtl[idx].OnEvent("click", "doClick") } } } oGui.AddButton("w130 h30 default","确认").OnEvent("click", "doDone") oGui.show() WinWaitClose("ahk_id " . oGui.Hwnd) CoordMode("tooltip", saveCoord) return this.arrIdx tips() { res := "" for _, idx in this.arrIdx res .= funcShow.call(arrs[idx]) . "`n" tooltip(rtrim(res, "`n")) } doExit() ;清空 { tooltip this.arrIdx := [] oGui.destroy } doDone() { tooltip oGui.destroy } doClick(ctl) { idxCtl := integer(ctl.name) if ctl.Value ;this.arrIdx.push(ctl.text) this.arrIdx.push(idxCtl) else this.arrIdx.RemoveAt(index(this.arrIdx, idxCtl)) obj := oGUI.pos tips() } selectAll() { for k, v in arrCtl ControlSetChecked(true, arrCtl[A_Index], "ahk_id " . oGUI.Hwnd) } selectNone() { for k, v in arrCtl ControlSetChecked(false, arrCtl[A_Index], "ahk_id " . oGUI.Hwnd) } selectReverse() { for k, v in arrCtl ControlSetChecked("Toggle", arrCtl[A_Index], "ahk_id " . oGUI.Hwnd) } ;在arr里的第1个序号 index(arr, val) { for k, v in arr { if (v = val) return k } return false } } }