; ========== CapsLockX ========== ; 名称:OneNote 增强 ; 版本:v2025.06.30 ; 作者:snomiao ; 联系:snomiao@gmail.com ; 支持:https://github.com/snomiao/CapsLockX ; 版权:Copyright © 2017-2024 Snowstar Laboratory. All Rights Reserved. ; ========== CapsLockX ========== ; ; save as utf8 with bom ; 引用剪贴板依赖 #Include Modules/WinClip/WinClipAPI.ahk #Include Modules/WinClip/WinClip.ahk global wc := new WinClip global ONENOTE_MATCHER := "- OneNote ahk_class Framework`:`:CFrame ahk_exe ONENOTE.EXE" Return ; 定义应用顶栏用到的函数 altSend(altKeys) { SetKeyDelay, 1, 60 ; 配置纠错 SendEvent {AltDown}%altKeys%{AltUp} } altSendEx(altKeys, suffix) { SetKeyDelay, 1, 60 ; 配置纠错 SendEvent {AltDown}%altKeys%{AltUp}%suffix% } StrJoin(sep, params*) { for idx, param in params { str .= param . sep } Return SubStr(str, 2, -StrLen(sep)) } GetFocusControlName() { ControlGetFocus, name, A Return name } ; 获取与IME无冲的编码字符串,用于 SendEvent (SEO: SendRaw SendInput) getAscStr(str) { charList := StrSplit(str) for key, val in charList { out .= "{Asc " . asc(val) . "}" } Return out } OneNote_Win11_Detect() { IServiceProvider := ComObjCreate("{C2F03A33-21F5-47FA-B4BB-156362A2F239}", "{6D5140C1-7436-11CE-8034-00AA006009FA}") IVirtualDesktopManagerInternal := ComObjQuery(IServiceProvider, "{C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B}", "{F31574D6-B682-4CDC-BD56-1827860ABEC6}") ObjRelease(IServiceProvider) if (IVirtualDesktopManagerInternal) { ; win10 return false } ; it is Win11 maybe return true } OneNote_SNODateStringGenerate() { FormatTime, TimeString, , (yyyyMMdd) return TimeString } OneNote_QuickTextInput(str) { SendInput {Text}%str% } OneNote快速笔记窗口启动(){ global ONENOTE_MATCHER if (OneNote_Win11_Detect()) { SendEvent #!n } else { ; SendEvent #n SendEvent #!n } OneNote窗口匹配串 := ".* " . ONENOTE_MATCHER WinWaitActive %OneNote窗口匹配串%, , 1 ; wait seconds if (ErrorLevel) { WinWait %OneNote窗口匹配串%, , 5 ; wait seconds if (ErrorLevel) { TrayTip, % t("错误"), % t("未找到OneNote窗口") return false } WinActivate %OneNote窗口匹配串% } ; set to topmost, (but not always on top). first, set always on top = off, and then set HWND_TOP ; use DllCall setwindowpos WinSet, AlwaysOnTop, Off, %OneNote窗口匹配串% DllCall("SetWindowPos", "UInt", WinExist(OneNote窗口匹配串), "UInt", 0, "Int", 0, "Int", 0, "Int", 0, "Int", 0, "UInt", 0x0002 | 0x0001) ; tooltip % t("OneNote 快速笔记窗口已启动") return true } OneNote主页启动(){ global ONENOTE_MATCHER HomePageMathcer := ".*(HOME|TODO).* " . ONENOTE_MATCHER WinActivate %HomePageMathcer% hWnd := WinActive(HomePageMathcer) if (!hWnd) { OneNote快速笔记窗口启动() }else{ ; make it top but not always on top WinSet, AlwaysOnTop, Off, %HomePageMathcer% DllCall("SetWindowPos", "UInt", hWnd, "UInt", 0, "Int", 0, "Int", 0, "Int", 0, "Int", 0, "UInt", 0x0002 | 0x0001) } ; SendEvent !{Home}^{Home}!{Enter}{Left} SendEvent !{Home}^{End}!{Enter} Return } OneNote搜索启动() { global ONENOTE_MATCHER FormatTime, TimeString, , yyyyMMdd TodayNoteMatcher := ".*" . TimeString . ".* " . ONENOTE_MATCHER WinActivate %TodayNoteMatcher% if (!WinActive(TodayNoteMatcher)) { OneNote快速笔记窗口启动() ; SendEvent ^{PgUp} } SendEvent ^e{Text}"" SendEvent {Left} OneNote_QuickTextInput(OneNote_SNODateStringGenerate()) SendEvent +{Left 10} Sleep, 200 SendEvent {Down}{Up 2}{End}+{Left}+{Home}+{Right} ; 定位到搜索框 Return } OneNote日记启动() { global ONENOTE_MATCHER FormatTime, TimeString, , yyyyMMdd TodayNoteMatcher := ".*" . TimeString . ".* " . ONENOTE_MATCHER ; Format yesterday's date Yesterday := A_Now Yesterday += -1, Days FormatTime, YesterdayTimeString, %Yesterday%, yyyyMMdd YesterdayNoteMatcher := ".*" . YesterdayTimeString . ".* " . ONENOTE_MATCHER ; Create matcher for today or yesterday notes TodayOrYesterdayNoteMatcher := ".*((" . TimeString . ")|(" . YesterdayTimeString . ")).* " . ONENOTE_MATCHER OneNoteMatcher := ".* " . ONENOTE_MATCHER WinActivate %TodayNoteMatcher% if (WinActive(TodayNoteMatcher)) { return true } ; deactivate if the OneNote window is active if (WinActive(OneNoteMatcher)) { ; activate the desktop to deactivate the OneNote window WinActivate, ahk_class Shell_TrayWnd WinWaitNotActive, %OneNoteMatcher%, , 5 } OneNote快速笔记窗口启动() WinWaitActive %OneNoteMatcher%, , 5 if (ErrorLevel) { return false } Tooltip % t("Switch to diary tab") WinGetTitle, CurrentTitle SendEvent ^{Tab} Tooltip % t("Wait for title change after switching tabs") WinWaitNotActive, %CurrentTitle%, , 3 WinWaitActive, %OneNoteMatcher%, , 3 Tooltip % t("Navigate to end of notebook") WinGetTitle, CurrentTitle SendEvent !{End} Tooltip % t("Wait for title change after navigation") WinWaitNotActive, %CurrentTitle%, , 3 WinWaitActive, %OneNoteMatcher%, , 3 Tooltip % t("Creating TODAY-NOTE") if(!WinActive(TodayNoteMatcher)){ SendEvent ^n Sleep, 300 把笔记时间显式填充到标题() WinWaitActive %TodayNoteMatcher%, , 5 if (ErrorLevel) { ; fail to create new note return false } return true } Return true } 笔记条目搜索结果复制整理向页面粘贴条数(){ global ONENOTE_MATCHER OneNote窗口匹配串 := ".* " . ONENOTE_MATCHER 条数 := 笔记条目搜索结果复制整理条数() ; WinWaitNotActive ahk_class NUIDialog ahk_exe ONENOTE.EXE, , 2 WinWaitActive %OneNote窗口匹配串%, , 5 ; wait for 5 seconds if(ErrorLevel) { TrayTip, % t("错误"), % t("未找到OneNote窗口") return } if (条数 >= 1) { SendEvent ^v{Left}{Delete} } return 条数 } ; 复制链接笔记页面的搜索结果 笔记条目搜索结果复制整理条数(){ WinWaitActive ahk_class NUIDialog ahk_exe ONENOTE.EXE, , 2 if(ErrorLevel) { TrayTip, % t("错误"), % t("搜索结果窗口不正确") return 0 } ; 标题 ClassNN: RICHEDIT60W3 ; 地址 ClassNN: RICHEDIT60W2 ; 定位到第一项 prev_addr := "" this_addr := "" links := "" prev_link := "" this_link := "" links_html := "" prev_link_html := "" this_link_html := "" samecount := 0 k := -1 ; 这里不加{Blind}{AltUp} 会出现连 ctrl也一起按下的bug...原因未明 SendEvent {Blind}{AltUp}!o{Down}{Home} loop, 10000 { ControlGetText, title, RICHEDIT60W3, A ControlGetText, addr, RICHEDIT60W2, A this_addr := addr isPage := !!RegExMatch(addr, "page-id=") Transform, title_html, HTML, %title% if (!isPage ) { title := "§ " title title_html := "§ " title_html } this_link := "[" title_html "]" "( " addr " )" "`n" this_link_html := "" title_html "" "
`n" SendEvent {Down} Sleep, 32 if (this_addr == prev_addr) { samecount++ if (samecount >= 2) { Break } } else { samecount := 0 prev_addr := this_addr k += 1 ; 这里用 prev_addr 意在去掉最后一条(一般是新建笔记) ; OneNote搜索默认倒字母序排列,这里把它正过来 /(20210401)发现不是这样的 ,决定在下面另外排序 links := prev_link . links prev_link := this_link ; 这里用 prev_link_html 意在去掉最后一条(一般是新建笔记) ; OneNote搜索默认倒字母序排列,这里把它正过来 /(20210401)发现不是这样的 ,决定在下面另外排序 links_html := prev_link_html . links_html prev_link_html := this_link_html } } ; links_html ; Clipboard := links Sort links Sort links_html ; remove the last break, 尽管没啥用 links_html := RegExReplace(links_html, "\
\n*?$", "") Clipboard := links ; Sleep 128 wc.SetText(links) wc.SetHTML(links_html) SendEvent {Escape} TrayTip, % k . t("条笔记链接已复制"), %links%, 1 return k } ; 注意win11下OneNote快速笔记热键变成了Win+Alt+N,而Win+N的新功能为打开消息中心 ; 原热键,打开快速笔记 ; $#n:: SendEvent #n #n:: OneNote快速笔记窗口启动() ; 打开 快速笔记 #!n:: OneNote主页启动() ; 打开 主页 #+n:: OneNote日记启动() ; OneNote搜索启动() ; 打开 OneNote 并精确匹配查找搜索笔记 ; 打开 UWP 版 OneNote 的快速笔记 ; $#+n:: Run "onenote-cmd://quicknote?onOpen=typing" ; #if OneNote搜索界面内() OneNote搜索界面内(){ global ONENOTE_MATCHER return (WinActive(".*" . ONENOTE_MATCHER) || WinActive("ahk_class ahk_class OneNote`:`:NavigationUIPopup ahk_exe ONENOTE.EXE")) } ; $^f:: ; $^e:: ; enhanced_search(){ ; ; 增强搜索,自动替换空格和引号等。 ; if (A_ThisHotkey = "$^e"){ ; SendEvent ^e ; }else{ ; SendEvent ^f ; } ; If ("RICHEDIT60W1" != GetFocusControlName()){ ; Return ; } ; Clipboard = ; SendEvent ^c ; ClipWait, 1 ; If ErrorLevel { ; Return ; } ; s1 := Clipboard ; a := StrSplit(s1) ; s2 := StrJoin(" ", a*) ; str := """" s1 """" " OR " """" s2 """" ; Clipboard := str ; SendEvent ^v ; Return ; } #if OneNote创建链接窗口内() OneNote创建链接窗口内(){ global ONENOTE_MATCHER return WinActive("ahk_class NUIDialog ahk_exe ONENOTE.EXE") } ; /:: CLX_ShowHelp OneNote创建链接窗口 ; 复制链接笔记页面的搜索结果 !+s:: 笔记条目搜索结果复制整理向页面粘贴条数() !s:: 笔记条目搜索结果复制整理条数() #if OneNote笔记编辑窗口内() OneNote笔记编辑窗口内(){ global ONENOTE_MATCHER return !CapsLockXMode && WinActive(".*" . ONENOTE_MATCHER) } F3:: 精确查找笔记() !m:: SendEvent ^!m ; 移动笔记 !+m:: SendEvent ^+g{AppsKey}m ; 移动分区 !f:: altSend("hg") ; 搜索标记 ^+PgUp:: SendEvent ^+g{Up}{Enter} ; 上一个页面切换 ^+PgDn:: SendEvent ^+g{Down}{Enter} ; 下一个页面切换 ^s:: SendEvent +{F9} ; 同步此笔记本 !n:: altSend("wpcn") ; 切换为无色背景 +!n:: altSend("wre") ; 切换为无格子背景 +Delete:: SendEvent {Escape}^a{Del} ; 快速删除当前行 !Delete:: SendEvent ^+a{Delete} ; 快速删除当前页面 !+Delete:: SendEvent ^+g{AppsKey}d ; 快速删除当前分区(并要求确认) ^w:: altSend("{F4}") ; 快速关闭窗口 ^+l:: SendEvent !+{Down}!+{Up} ; 选中行 ^d:: SendEvent {Right}^{Left}^+{Right} ; 选中当前词(目前来说会带上词右边的空格) !q:: altSend("dh") ;换成手形Tools ; 拖动 !w:: altSend("dl") ; 套锁 !e:: altSend("dek") ; 橡皮 !s:: altSend("dt") ; 输入 !a:: altSend("dn") ; 增加空白 !+r:: altSend("w1") ; 视图 - 缩放到1 !r:: altSend("wi2") ; 视图 - 缩放到页面宽度 !d:: altSendEx("dp", "{Home}") ; 打开换笔盘,定位到第一支笔 !k:: 将当前关键词搜索到的相关页面链接在下方展开() !t:: 把笔记时间显式填充到标题() !-:: 自动2维化公式() ^+c:: 纯文本复制() ^+v:: 纯文本粘贴() ~Enter:: 链接安全警告自动确认() !+p:: 段落链接复制() !p:: 页面链接复制() F2:: SendEvent ^+t ; 重命名笔记 +F2:: SendEvent ^+g{AppsKey}r ; 重命名分区 !F2:: SendEvent ^+a{AppsKey}l ; 页面链接复制 +^Enter:: OneNote_ToggleTODO() ; 切换 OneNote TODO 前缀状态 (Beta) OneNote_ToggleTODO(){ ; request clipboard backup:=ClipboardAll Clipboard:="" ; select current line 行は選る Send {Home}^a{Home}+{End}^c ; get clipboard ClipWait, 2 if(ErrorLevel) { Clipboard := backup return } s := clipboard Clipboard := backup ; TURNING TODO STATES isTODO := !!RegExMatch(s, "^TODO") if (isTODO ) { so := RegExReplace(s, "^TODO ?", "DOING ") SendEvent, {Text}%so% SendEvent, ^a{End} return } isDOING := !!RegExMatch(s, "^DOING") if (isDOING ) { so := RegExReplace(s, "^DOING ?", "DONE ") SendEvent, {Text}%so% SendEvent, ^a{End} return } isDONE := !!RegExMatch(s, "^DONE") if (isDONE ) { so := RegExReplace(s, "^DONE ?", "") SendEvent, {Text}%so% SendEvent, ^a{End} return } ; is nothing so := RegExReplace(s, "^ ?", "TODO ") SendEvent, {Text}%so% SendEvent, ^a{End} return } 把笔记时间显式填充到标题(){ backup := ClipboardAll Clipboard:="" ; copy date then focus to title SetKeyDelay, 0, 0 SendEvent ^+t^{Down}^c{Left}^{Up} ClipWait, 2 if(ErrorLevel) { Clipboard := backup return } dateString := Trim(Clipboard, "`r`n") Clipboard := backup calcCode = ( '(' + new Date(+new Date( "%dateString%" .replace(/星期.|.曜日/g, '') .replace(/日/g, '') .replace(/年|月/g,'-') .trim()) +-new Date().getTimezoneOffset()*60e3) .toISOString() .slice(0, 10) .replace(/-/g, '') + ')' ) result := Func("SafetyEvalJavascript").Call(calcCode) SendEvent, {Text}%result% } ; 按回车后1秒内,如果出现了安全警告窗口,则自动按 Yes 链接安全警告自动确认(){ waitWindow := "ahk_class NUIDialog ahk_exe ONENOTE.EXE" WinWaitActive %waitWindow%, , 1 if (!ErrorLevel) SendEvent !y } ; 自动2维化公式 自动2维化公式(){ SendEvent != Sleep, 200 altSend("jp") } ; 纯文本复制 纯文本复制(){ Clipboard = SendEvent ^c ClipWait, 1 Clipboard := Clipboard } ; 纯文本粘贴 纯文本粘贴(){ Clipboard := Clipboard SendEvent ^v } ; 复制段落链接(并清洗成 onenote 链接(段落链接的url不管用。。 段落链接复制(){ Clipboard := "" SendEvent {AppsKey}pp{Enter} ClipWait, 1 if(ErrorLevel) Return Clipboard := Func("SafetyEvalJavascript").Call("``" Clipboard "``.match(/^(onenote:.*)$/mi)?.[0]||""""") } ; 复制页面链接(并清洗成 onenote 链接 页面链接复制(){ Clipboard := "" SendEvent ^+a{AppsKey}lp ClipWait, 1 if (ErrorLevel) Return Clipboard := Func("SafetyEvalJavascript").Call("``" Clipboard "``.match(/^(onenote:.*)$/mi)?.[0]||""""") } 精确查找笔记(){ SendEvent ^e{Text}"" SendEvent {Left} } 将当前关键词搜索到的相关页面链接在下方展开(){ Clipboard := "" SendEvent ^a^c ClipWait, 1 if(ErrorLevel) { TrayTip, % t("错误"), % t("OneNote 内容未能复制成功,5秒内按 Ctrl + C 可手动复制并尝试继续流程") ClipWait, 5 if(ErrorLevel) { TrayTip, % t("错误"), % t("OneNote 内容未能复制成功") return } } SendEvent {Right}{Enter}{Tab}^k WinWaitActive ahk_class NUIDialog ahk_exe ONENOTE.EXE, , 2 ; 输入搜索内容 ControlSetText, RICHEDIT60W1, %Clipboard%, A ToolTip, 放开Alt键继续 KeyWait, Alt, D T60 ; wait for 60 seconds if(ErrorLevel) { ToolTip TrayTip, % t("错误"), % t("超时未按下Alt键") return } KeyWait, Alt, T60 ; wait for 60 seconds if(ErrorLevel) { ToolTip TrayTip, % t("错误"), % t("超时未放开Alt键") return } ToolTip 条数 := 笔记条目搜索结果复制整理向页面粘贴条数() if(条数 == 1) { SendEvent +{Tab} SendEvent {Home}{Left}^a{Delete} } } OneNoteNoteSplit() { SendEvent {Home}[[{End}]] ; 将内容做成单独链接 } $!+k:: OneNoteNoteSplit() $!1:: SendEvent !+1 ; 大纲折叠展开到1 $!2:: SendEvent !+2 ; 大纲折叠展开到2 $!3:: SendEvent !+3 ; 大纲折叠展开到3 $!4:: SendEvent !+4 ; 大纲折叠展开到4 $!5:: SendEvent !+5 ; 大纲折叠展开到5 $!6:: SendEvent !+6 ; 大纲折叠展开到6 $!7:: SendEvent !+7 ; 大纲折叠展开到7 $!`:: altSendEx("dp", "{Down 2}{Left}") ; 自定义颜色 $!+`:: altSend("dc") ; 自定义颜色 $!v:: SendEvent !h!i ; 自定义颜色 $![:: altSendEx("w", "{Down}{Tab 3}{Enter}") ; 调整缩放+ $!]:: altSendEx("w", "{Down}{Tab 4}{Enter}") ; 调整缩放- $!\:: altSendEx("w", "{Down}{Tab 5}{Enter}") ; 调整缩放复原 ; 调整字体 $^[:: altSendEx("h", "{Down}{Tab 1}{Up 2}{Enter}") $^]:: altSendEx("h", "{Down}{Tab 1}{Down 2}{Enter}") $^\:: altSendEx("h", "{Down}+{Tab 1}{Enter}") #if OneNote换笔界面() OneNote换笔界面(){ return WinActive("ahk_class Net UI Tool Window ahk_exe ONENOTE.EXE") && A_PriorHotkey=="!d" } $1:: SendEvent {Right 0}{Enter} ; 向第1行第1支笔切换 $2:: SendEvent {Right 1}{Enter} ; 向第1行第2支笔切换 $3:: SendEvent {Right 2}{Enter} ; 向第1行第3支笔切换 $4:: SendEvent {Right 3}{Enter} ; 向第1行第4支笔切换 $5:: SendEvent {Right 4}{Enter} ; 向第1行第5支笔切换 $6:: SendEvent {Right 5}{Enter} ; 向第1行第6支笔切换 $7:: SendEvent {Right 6}{Enter} ; 向第1行第7支笔切换 $+1:: SendEvent {Down 1}{Right 0}{Enter} ; 向第2行第1支笔切换 $+2:: SendEvent {Down 1}{Right 1}{Enter} ; 向第2行第2支笔切换 $+3:: SendEvent {Down 1}{Right 2}{Enter} ; 向第2行第3支笔切换 $+4:: SendEvent {Down 1}{Right 3}{Enter} ; 向第2行第4支笔切换 $+5:: SendEvent {Down 1}{Right 4}{Enter} ; 向第2行第5支笔切换 $+6:: SendEvent {Down 1}{Right 5}{Enter} ; 向第2行第6支笔切换 $+7:: Send {Down 1}{Right 6}{Enter} ; 向第2行第7支笔切换 #if 名为剪贴板的OneNote窗口存在() 名为剪贴板的OneNote窗口存在(){ return WinExist("剪贴板.*|Clipboard ahk_class Framework`:`:CFrame ahk_exe ONENOTE.EXE") } ^c:: OneNote剪贴板收集() OneNote剪贴板收集(){ Clipboard := "" SendEvent, ^c hwndOneNote := 名为剪贴板的OneNote窗口存在() if (!hwndOneNote) Return ; ; 通常在弹起时触发 ClipWait, 2, 1 ; 2 secons if(ErrorLevel) { TrayTip, error, % t("复制失败") Return } WinGet, current, ID, A BlockInput, on WinActivate, ahk_id %hwndOneNote% WinSet, AlwaysOnTop, On, ahk_id %hwndOneNote% FormatTime, timeString, , (yyyyMMdd.HHmmss) SendEvent, ^{End}^{Enter} SendEvent, {text}%timeString% SendEvent, {Tab}^v Sleep 128 WinActivate, ahk_id %current% BlockInput, off }