v1
#NoEnv
#Persistent
#SingleInstance Force
SendMode Input
SetWorkingDir %A_ScriptDir%
SetBatchLines -1
; 设置坐标模式
CoordMode, Mouse, Screen
CoordMode, ToolTip, Screen
CoordMode, Gui, Screen
; --- 全局变量 ---
global TyporaConfigFile := A_ScriptDir "\typora_config.ini"
global CurrentFileConfig := "current_file.ini"
global RemainingFilesConfig := "remaining_files.ini"
global SignalFile := A_ScriptDir "\signal.ini"
global LogFile := A_ScriptDir "\typora_log.txt"
global TyporaPath, MainFolder, SubFolder
global ClickPos1X, ClickPos1Y, ClickPos2X, ClickPos2Y
global UseRecordedName
global AutoTriggerNext
global StartTriggerMode
global NextTriggerMode
global RemainingFiles
global StartTriggerKey
global NextTriggerKey
global ToggleGuiKey
global IsToggleGuiKeyCustomized
global MainGuiHwnd
global FloatGuiHwnd
global GuiVisible := 1
global FloatVisible := 1
global SignalMonitorName := "TriggerTypora"
global SignalNextName := "TriggerSender"
global IsTyporaMonitoring := 0
global StartTriggerKeyStatus := "未绑定"
global NextTriggerKeyStatus := "未绑定"
global ToggleGuiKeyStatus := "未绑定"
global DetectionStatus := "未启动"
global SignalValue := 0
global Countdown := 5 ; 倒计时初始值(5秒,与信号检测周期同步)
; --- 实用函数 ---
CleanHotkeyString(hotkey) {
hotkey := StrReplace(hotkey, "{", "")
hotkey := StrReplace(hotkey, "}", "")
return hotkey
}
ConvertHotkeyToSendFormat(hotkey) {
sendKey := hotkey
if (RegExMatch(sendKey, "^[0-9]$")) {
; 数字键直接发送
} else if (sendKey = "XButton1" || sendKey = "XButton2" || RegExMatch(sendKey, "^F[1-9][0-2]?$")) {
sendKey := "{" sendKey "}"
} else {
if (InStr(hotkey, "^"))
sendKey := "^" sendKey
if (InStr(hotkey, "!"))
sendKey := "!" sendKey
if (InStr(hotkey, "+"))
sendKey := "+" sendKey
}
LogMessage("ConvertHotkeyToSendFormat: Input=" hotkey ", Output=" sendKey)
return sendKey
}
LogMessage(message) {
FormatTime, CurrentTime,, yyyy-MM-dd HH:mm:ss
FileAppend, [%CurrentTime%] %message%`n, %LogFile%
}
; --- 加载配置并初始化 ---
IfNotExist, %TyporaConfigFile%
{
FileSelectFile, TyporaPath, 3, , 请选择 Typora.exe 文件, Executable Files (*.exe)
if (TyporaPath = "") {
MsgBox, 你没有选择 Typora.exe 文件,脚本将退出。
ExitApp
}
FileSelectFolder, MainFolder, , 3, 请选择主文件夹路径
if (MainFolder = "") {
MsgBox, 你没有选择主文件夹路径,脚本将退出。
ExitApp
}
IniWrite, %TyporaPath%, %TyporaConfigFile%, Settings, TyporaPath
IniWrite, %MainFolder%, %TyporaConfigFile%, Settings, MainFolder
IniWrite, %SubFolder%, %TyporaConfigFile%, Settings, SubFolder
IniWrite, 100, %TyporaConfigFile%, ClickPositions, Pos1X
IniWrite, 100, %TyporaConfigFile%, ClickPositions, Pos1Y
IniWrite, 200, %TyporaConfigFile%, ClickPositions, Pos2X
IniWrite, 200, %TyporaConfigFile%, ClickPositions, Pos2Y
IniWrite, 1, %TyporaConfigFile%, Settings, UseRecordedName
IniWrite, 0, %TyporaConfigFile%, Settings, AutoTriggerNext
IniWrite, 1, %TyporaConfigFile%, Hotkeys, StartTriggerKey
IniWrite, ^!s, %TyporaConfigFile%, Hotkeys, NextTriggerKey
IniWrite, #t, %TyporaConfigFile%, Hotkeys, ToggleGuiKey
IniWrite, 0, %TyporaConfigFile%, Hotkeys, IsToggleGuiKeyCustomized
IniWrite, 1, %TyporaConfigFile%, Settings, GuiVisible
IniWrite, 0, %TyporaConfigFile%, Settings, StartTriggerMode
IniWrite, 0, %TyporaConfigFile%, Settings, NextTriggerMode
IniWrite, 0, %TyporaConfigFile%, Settings, IsTyporaMonitoring
}
IniRead, TyporaPath, %TyporaConfigFile%, Settings, TyporaPath
IniRead, MainFolder, %TyporaConfigFile%, Settings, MainFolder
IniRead, SubFolder, %TyporaConfigFile%, Settings, SubFolder, ""
IniRead, ClickPos1X, %TyporaConfigFile%, ClickPositions, Pos1X, 100
IniRead, ClickPos1Y, %TyporaConfigFile%, ClickPositions, Pos1Y, 100
IniRead, ClickPos2X, %TyporaConfigFile%, ClickPositions, Pos2X, 200
IniRead, ClickPos2Y, %TyporaConfigFile%, ClickPositions, Pos2Y, 200
IniRead, UseRecordedName, %TyporaConfigFile%, Settings, UseRecordedName, 1
IniRead, AutoTriggerNext, %TyporaConfigFile%, Settings, AutoTriggerNext, 0
IniRead, StartTriggerKey, %TyporaConfigFile%, Hotkeys, StartTriggerKey, 1
IniRead, NextTriggerKey, %TyporaConfigFile%, Hotkeys, NextTriggerKey, ^!s
IniRead, ToggleGuiKey, %TyporaConfigFile%, Hotkeys, ToggleGuiKey, #t
IniRead, IsToggleGuiKeyCustomized, %TyporaConfigFile%, Hotkeys, IsToggleGuiKeyCustomized, 0
IniRead, GuiVisible, %TyporaConfigFile%, Settings, GuiVisible, 1
IniRead, StartTriggerMode, %TyporaConfigFile%, Settings, StartTriggerMode, 0
IniRead, NextTriggerMode, %TyporaConfigFile%, Settings, NextTriggerMode, 0
IniRead, IsTyporaMonitoring, %TyporaConfigFile%, Settings, IsTyporaMonitoring, 0
StartTriggerKey := CleanHotkeyString(StartTriggerKey)
NextTriggerKey := CleanHotkeyString(NextTriggerKey)
ToggleGuiKey := CleanHotkeyString(ToggleGuiKey)
IfNotExist, %RemainingFilesConfig%
{
IniWrite, 0, %RemainingFilesConfig%, Settings, RemainingFiles
}
IniRead, RemainingFiles, %RemainingFilesConfig%, Settings, RemainingFiles, 0
IfNotExist, %SignalFile%
{
IniWrite, 0, %SignalFile%, Signals, TriggerSender
IniWrite, 0, %SignalFile%, Signals, TriggerMonitor
IniWrite, 0, %SignalFile%, Signals, TriggerTypora
IniWrite, 0, %SignalFile%, Signals, ReadyForNote
}
IniWrite, 0, %SignalFile%, Signals, TriggerSender
IniWrite, 0, %SignalFile%, Signals, TriggerMonitor
IniWrite, 0, %SignalFile%, Signals, TriggerTypora
IniWrite, 0, %SignalFile%, Signals, ReadyForNote
; --- 创建主 GUI ---
CreateMainGui:
Gui, Main:+LastFound +Resize
MainGuiHwnd := WinExist()
StartTriggerModeKeyChecked := (StartTriggerMode = 0) ? 1 : 0
StartTriggerModeSignalChecked := (StartTriggerMode = 1) ? 1 : 0
NextTriggerModeKeyChecked := (NextTriggerMode = 0) ? 1 : 0
NextTriggerModeSignalChecked := (NextTriggerMode = 1) ? 1 : 0
if (!IsTyporaMonitoring) {
DetectionStatus := "监控未启动"
} else {
DetectionStatus := "监控运行中"
}
; 横向布局:所有 GroupBox 并排显示
Gui, Main:Add, GroupBox, x10 y10 w240 h260, 路径设置
Gui, Main:Add, Text, x20 y30 w220, Typora 路径: %TyporaPath%
Gui, Main:Add, Button, x20 y60 w220 gChangeTyporaPath, 更改 Typora 路径
Gui, Main:Add, GroupBox, x260 y10 w240 h260, 文件夹设置
Gui, Main:Add, Text, x270 y30 w220, 主文件夹: %MainFolder%
Gui, Main:Add, Button, x270 y60 w220 gSelectMainFolder, 选择主文件夹
Gui, Main:Add, Text, x270 y90 w220, 子文件夹: %SubFolder%
Gui, Main:Add, Button, x270 y120 w220 gSelectSubFolder, 选择/创建子文件夹
Gui, Main:Add, GroupBox, x510 y10 w240 h260, 功能设置
Gui, Main:Add, Text, x520 y30 w220 vRemainingFilesDisplay, 剩余文件: %RemainingFiles%
Gui, Main:Add, Button, x520 y60 w220 gSetClickPositions, 设置点击位置
Gui, Main:Add, CheckBox, x520 y90 w220 vUseRecordedName gSaveUseRecordedName Checked%UseRecordedName%, 自动读取文件名
Gui, Main:Add, CheckBox, x520 y120 w220 vAutoTriggerNext gUpdateAutoTrigger Checked%AutoTriggerNext%, 自动触发下一个文件
Gui, Main:Add, Text, x520 y150 w220, 被触发方式:
Gui, Main:Add, Radio, x530 y170 w100 vStartTriggerModeKey gSaveStartTriggerMode Checked%StartTriggerModeKeyChecked%, 快捷键触发
Gui, Main:Add, Radio, x630 y170 w100 vStartTriggerModeSignal gSaveStartTriggerMode Checked%StartTriggerModeSignalChecked%, 信号量触发
Gui, Main:Add, Text, x520 y200 w220, 触发下一脚本:
Gui, Main:Add, Radio, x530 y220 w100 vNextTriggerModeKey gSaveNextTriggerMode Checked%NextTriggerModeKeyChecked%, 快捷键触发
Gui, Main:Add, Radio, x630 y220 w100 vNextTriggerModeSignal gSaveNextTriggerMode Checked%NextTriggerModeSignalChecked%, 信号量触发
Gui, Main:Add, GroupBox, x760 y10 w240 h260, 快捷键设置
Gui, Main:Add, Text, x770 y30 w220 vToggleGuiKeyDisplay, 显示/隐藏 GUI: %ToggleGuiKey% (%ToggleGuiKeyStatus%)
Gui, Main:Add, Button, x770 y60 w220 gSetToggleGuiKey, 设置显示/隐藏快捷键
Gui, Main:Add, Text, x770 y90 w220 vStartTriggerKeyDisplay, 被触发快捷键: %StartTriggerKey% (%StartTriggerKeyStatus%)
Gui, Main:Add, Button, x770 y120 w220 gSetStartTriggerKey, 设置被触发快捷键
Gui, Main:Add, Text, x770 y150 w220 vNextTriggerKeyDisplay, 下一触发快捷键: %NextTriggerKey% (%NextTriggerKeyStatus%)
Gui, Main:Add, Button, x770 y180 w220 gSetNextTriggerKey, 设置下一触发快捷键
Gui, Main:Add, GroupBox, x1010 y10 w240 h260, 状态监控
Gui, Main:Add, Text, x1020 y30 w220 vDetectionStatusDisplay, 检测状态: %DetectionStatus%
Gui, Main:Add, Text, x1020 y60 w220 vCountdownDisplay, 信号检测倒计时: %Countdown% 秒
Gui, Main:Add, Text, x1020 y90 w220 vSignalStatusDisplay, 信号量 TriggerTypora: %SignalValue%
Gui, Main:Add, Button, x1020 y120 w70 gToggleFloatWindow, 悬浮窗
Gui, Main:Add, Button, x1095 y120 w70 gStartMonitoring, 开始监控
Gui, Main:Add, Button, x1170 y120 w70 gRunTypora Default, 运行 Typora
if (GuiVisible = 1) {
Gui, Main:Show, w1250 h300, Typora 启动器
LogMessage("GUI 创建并显示")
} else {
Gui, Main:Hide
LogMessage("GUI 创建并隐藏")
}
return
; --- 选择主文件夹 ---
SelectMainFolder:
FileSelectFolder, newMainFolder, , 3, 请选择主文件夹
if (newMainFolder != "") {
MainFolder := newMainFolder
IniWrite, %MainFolder%, %TyporaConfigFile%, Settings, MainFolder
SubFolder := "" ; 重置子文件夹
IniWrite, %SubFolder%, %TyporaConfigFile%, Settings, SubFolder
Gui, Main:Destroy
Gosub, CreateMainGui
MsgBox, 主文件夹已更新为: %MainFolder%
LogMessage("主文件夹更新为: " MainFolder)
}
return
; --- 选择/创建子文件夹 ---
SelectSubFolder:
if (MainFolder = "") {
MsgBox, 请先选择主文件夹!
return
}
Gui, SubFolderGui:New, +AlwaysOnTop
Gui, SubFolderGui:Add, Text, , 选择或创建子文件夹:
Gui, SubFolderGui:Add, ListBox, vSubFolderList w300 h200, % GetSubFolders(MainFolder)
Gui, SubFolderGui:Add, Edit, vNewSubFolder w300,
Gui, SubFolderGui:Add, Button, gCreateNewSubFolder, 创建新子文件夹
Gui, SubFolderGui:Add, Button, default gSelectExistingSubFolder, 选择
Gui, SubFolderGui:Show
return
GetSubFolders(folder) {
subFolders := ""
Loop, Files, %folder%\*, D
{
subFolders .= A_LoopFileName "|"
}
return subFolders
}
CreateNewSubFolder:
Gui, SubFolderGui:Submit
if (NewSubFolder != "") {
newSubFolderPath := MainFolder "\" NewSubFolder
if !FileExist(newSubFolderPath) {
FileCreateDir, %newSubFolderPath%
if (ErrorLevel = 0) {
SubFolder := NewSubFolder
IniWrite, %SubFolder%, %TyporaConfigFile%, Settings, SubFolder
Gui, SubFolderGui:Destroy
Gui, Main:Destroy
Gosub, CreateMainGui
MsgBox, 子文件夹 %SubFolder% 已创建并选择。
LogMessage("创建并选择子文件夹: " SubFolder)
} else {
MsgBox, 创建子文件夹失败!
}
} else {
MsgBox, 子文件夹 %NewSubFolder% 已存在!
}
} else {
MsgBox, 请输入子文件夹名称!
}
return
SelectExistingSubFolder:
Gui, SubFolderGui:Submit
if (SubFolderList != "") {
SubFolder := SubFolderList
IniWrite, %SubFolder%, %TyporaConfigFile%, Settings, SubFolder
Gui, SubFolderGui:Destroy
Gui, Main:Destroy
Gosub, CreateMainGui
MsgBox, 子文件夹 %SubFolder% 已选择。
LogMessage("选择子文件夹: " SubFolder)
} else {
MsgBox, 请选择一个子文件夹!
}
return
; --- 创建悬浮窗 ---
CreateFloatWindow:
Gui, Float:+LastFound +AlwaysOnTop +Border
FloatGuiHwnd := WinExist()
if (!FloatGuiHwnd) {
LogMessage("悬浮窗创建失败:无法获取窗口句柄")
MsgBox, 悬浮窗创建失败,请检查脚本!
return
}
Gui, Float:Add, Text, w300 vFloatSignalDisplay, 信号量 TriggerTypora: %SignalValue% (倒计时: %Countdown% 秒)
Gui, Float:Show, x10 y10 w320 h30
FloatVisible := 1
LogMessage("悬浮窗创建成功,句柄: " FloatGuiHwnd ",坐标: (10, 10),大小: (320, 30)")
return
; --- 更新悬浮窗和倒计时 ---
UpdateFloatWindow:
IniRead, SignalValue, %SignalFile%, Signals, %SignalMonitorName%, 0
GuiControl, Float:, FloatSignalDisplay, 信号量 TriggerTypora: %SignalValue% (倒计时: %Countdown% 秒)
GuiControl, Main:, SignalStatusDisplay, 信号量 TriggerTypora: %SignalValue%
GuiControl, Main:, CountdownDisplay, 信号检测倒计时: %Countdown% 秒
if (WinExist("ahk_id " FloatGuiHwnd)) {
LogMessage("悬浮窗更新: SignalValue=" SignalValue ", Countdown=" Countdown)
} else {
LogMessage("悬浮窗更新失败: 窗口不存在")
}
return
UpdateCountdown:
if (!IsTyporaMonitoring) {
return
}
Countdown -= 1
if (Countdown <= 0) {
Countdown := 5 ; 重置倒计时
Gosub, MonitorSignal ; 到达周期时检测信号量
}
Gosub, UpdateFloatWindow
return
; --- 切换悬浮窗 ---
ToggleFloatWindow:
FloatVisible := !FloatVisible
if (FloatVisible = 1) {
Gui, Float:Show
LogMessage("悬浮窗显示,句柄: " FloatGuiHwnd)
} else {
Gui, Float:Hide
LogMessage("悬浮窗隐藏,句柄: " FloatGuiHwnd)
}
return
; --- 开始监控 ---
StartMonitoring:
IsTyporaMonitoring := 1
IniWrite, %IsTyporaMonitoring%, %TyporaConfigFile%, Settings, IsTyporaMonitoring
SetTimer, UpdateCountdown, 1000 ; 每秒更新倒计时
DetectionStatus := "监控运行中"
GuiControl,, DetectionStatusDisplay, 检测状态: %DetectionStatus%
LogMessage("监控已启用")
return
; --- 绑定快捷键 ---
BindHotkeys() {
if (IsToggleGuiKeyCustomized = 0) {
ToggleGuiKey := "#t"
IniWrite, %ToggleGuiKey%, %TyporaConfigFile%, Hotkeys, ToggleGuiKey
LogMessage("未自定义 ToggleGuiKey,使用默认值: " ToggleGuiKey)
}
try {
Hotkey, %ToggleGuiKey%, ToggleGui
ToggleGuiKeyStatus := "已绑定"
GuiControl,, ToggleGuiKeyDisplay, 显示/隐藏 GUI: %ToggleGuiKey% (%ToggleGuiKeyStatus%)
LogMessage("绑定 ToggleGuiKey: " ToggleGuiKey " 成功")
} catch e {
ToggleGuiKey := "#t"
ToggleGuiKeyStatus := "恢复默认"
IsToggleGuiKeyCustomized := 0
IniWrite, %ToggleGuiKey%, %TyporaConfigFile%, Hotkeys, ToggleGuiKey
IniWrite, %IsToggleGuiKeyCustomized%, %TyporaConfigFile%, Hotkeys, IsToggleGuiKeyCustomized
Hotkey, %ToggleGuiKey%, ToggleGui
GuiControl,, ToggleGuiKeyDisplay, 显示/隐藏 GUI: %ToggleGuiKey% (%ToggleGuiKeyStatus%)
LogMessage("绑定 ToggleGuiKey 失败,恢复默认: " ToggleGuiKey ",错误: " e)
}
if (StartTriggerMode = 0) {
try {
Hotkey, %StartTriggerKey%, RunTypora
StartTriggerKeyStatus := "已绑定"
GuiControl,, StartTriggerKeyDisplay, 被触发快捷键: %StartTriggerKey% (%StartTriggerKeyStatus%)
LogMessage("绑定 StartTriggerKey: " StartTriggerKey " 成功")
} catch e {
StartTriggerKey := "1"
StartTriggerKeyStatus := "恢复默认"
IniWrite, %StartTriggerKey%, %TyporaConfigFile%, Hotkeys, StartTriggerKey
Hotkey, %StartTriggerKey%, RunTypora
GuiControl,, StartTriggerKeyDisplay, 被触发快捷键: %StartTriggerKey% (%StartTriggerKeyStatus%)
LogMessage("绑定 StartTriggerKey 失败,恢复默认: " StartTriggerKey ",错误: " e)
}
}
NextTriggerKeyStatus := "已设置"
GuiControl,, NextTriggerKeyDisplay, 下一触发快捷键: %NextTriggerKey% (%NextTriggerKeyStatus%)
LogMessage("NextTriggerKey 已设置: " NextTriggerKey)
}
; --- 监测信号量 ---
MonitorSignal:
if (IsTyporaMonitoring) {
IniRead, SignalValue, %SignalFile%, Signals, %SignalMonitorName%, 0
LogMessage("MonitorSignal: SignalValue=" SignalValue " for " SignalMonitorName)
if (SignalValue = 1 && StartTriggerMode = 1) {
ToolTip, 检测到信号量 %SignalMonitorName%=1,触发 Typora
Sleep, 1000
ToolTip
Gosub, RunTypora
IniWrite, 0, %SignalFile%, Signals, %SignalMonitorName%
SignalValue := 0
LogMessage("信号量触发,执行 RunTypora 并重置 " SignalMonitorName "=0")
}
}
Gosub, UpdateFloatWindow
return
; --- 切换 GUI 可见性 ---
ToggleGui:
GuiVisible := !GuiVisible
IniWrite, %GuiVisible%, %TyporaConfigFile%, Settings, GuiVisible
if (GuiVisible = 1) {
Gui, Main:Show,, Typora 启动器
LogMessage("GUI 显示")
} else {
Gui, Main:Hide
LogMessage("GUI 隐藏")
}
return
; --- 更改 Typora 路径 ---
ChangeTyporaPath:
FileSelectFile, newTyporaPath, 3, , 请选择新的 Typora.exe 文件, Executable Files (*.exe)
if (newTyporaPath != "") {
IniWrite, %newTyporaPath%, %TyporaConfigFile%, Settings, TyporaPath
TyporaPath := newTyporaPath
Gui, Main:Destroy
Gosub, CreateMainGui
MsgBox, Typora 路径已更新为: %newTyporaPath%
LogMessage("Typora 路径更新为: " newTyporaPath)
}
return
; --- 设置点击位置 ---
SetClickPositions:
MsgBox, 请点击第一个位置(支持双屏),然后按 Enter 键确认。
KeyWait, LButton, D
MouseGetPos, ClickPos1X, ClickPos1Y
ToolTip, 位置1: %ClickPos1X%, %ClickPos1Y%
Sleep, 500
ToolTip
MsgBox, 请点击第二个位置(支持双屏),然后按 Enter 键确认。
KeyWait, LButton, D
MouseGetPos, ClickPos2X, ClickPos2Y
ToolTip, 位置2: %ClickPos2X%, %ClickPos2Y%
Sleep, 500
ToolTip
MsgBox, 位置已设置:位置1 (%ClickPos1X%, %ClickPos1Y%), 位置2 (%ClickPos2X%, %ClickPos2Y%)
IniWrite, %ClickPos1X%, %TyporaConfigFile%, ClickPositions, Pos1X
IniWrite, %ClickPos1Y%, %TyporaConfigFile%, ClickPositions, Pos1Y
IniWrite, %ClickPos2X%, %TyporaConfigFile%, ClickPositions, Pos2X
IniWrite, %ClickPos2Y%, %TyporaConfigFile%, ClickPositions, Pos2Y
Gui, Main:Destroy
Gosub, CreateMainGui
LogMessage("点击位置设置: Pos1=(" ClickPos1X "," ClickPos1Y "), Pos2=(" ClickPos2X "," ClickPos2Y ")")
return
; --- 保存 UseRecordedName 设置 ---
SaveUseRecordedName:
Gui, Main:Submit, NoHide
IniWrite, %UseRecordedName%, %TyporaConfigFile%, Settings, UseRecordedName
Gui, Main:Destroy
Gosub, CreateMainGui
LogMessage("UseRecordedName 设置为: " UseRecordedName)
return
; --- 更新 AutoTrigger 设置 ---
UpdateAutoTrigger:
Gui, Main:Submit, NoHide
IniWrite, %AutoTriggerNext%, %TyporaConfigFile%, Settings, AutoTriggerNext
Gui, Main:Destroy
Gosub, CreateMainGui
LogMessage("AutoTriggerNext 设置为: " AutoTriggerNext)
return
; --- 保存 Start Trigger 模式 ---
SaveStartTriggerMode:
Gui, Main:Submit, NoHide
StartTriggerMode := (StartTriggerModeKey = 1) ? 0 : 1
IniWrite, %StartTriggerMode%, %TyporaConfigFile%, Settings, StartTriggerMode
if (StartTriggerMode = 0) {
try {
Hotkey, %StartTriggerKey%, RunTypora
StartTriggerKeyStatus := "已绑定"
GuiControl,, StartTriggerKeyDisplay, 被触发快捷键: %StartTriggerKey% (%StartTriggerKeyStatus%)
LogMessage("绑定快捷键 StartTriggerKey: " StartTriggerKey " 成功")
} catch e {
StartTriggerKeyStatus := "绑定失败"
LogMessage("绑定快捷键失败: " e)
}
} else {
try {
Hotkey, %StartTriggerKey%, Off
StartTriggerKeyStatus := "未绑定"
GuiControl,, StartTriggerKeyDisplay, 被触发快捷键: %StartTriggerKey% (%StartTriggerKeyStatus%)
LogMessage("解除快捷键绑定 StartTriggerKey: " StartTriggerKey)
} catch {
}
}
Gui, Main:Destroy
Gosub, CreateMainGui
LogMessage("StartTriggerMode 设置为: " (StartTriggerMode = 0 ? "快捷键" : "信号量"))
return
; --- 保存 Next Trigger 模式 ---
SaveNextTriggerMode:
Gui, Main:Submit, NoHide
NextTriggerMode := (NextTriggerModeKey = 1) ? 0 : 1
IniWrite, %NextTriggerMode%, %TyporaConfigFile%, Settings, NextTriggerMode
Gui, Main:Destroy
Gosub, CreateMainGui
LogMessage("NextTriggerMode 设置为: " (NextTriggerMode = 0 ? "快捷键" : "信号量"))
return
; --- 设置 Start Trigger 快捷键 ---
SetStartTriggerKey:
Gui, KeyInput:New, +AlwaysOnTop
Gui, KeyInput:Add, CheckBox, vUseCtrl gUpdateHotkeyPreview, 使用 Ctrl
Gui, KeyInput:Add, CheckBox, vUseAlt gUpdateHotkeyPreview xm, 使用 Alt
Gui, KeyInput:Add, CheckBox, vUseWin gUpdateHotkeyPreview xm, 使用 Win
Gui, KeyInput:Add, Text, xm, 选择按键:
Gui, KeyInput:Add, DropDownList, vHotkeyChoice gUpdateHotkeyPreview, A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|F1|F2|F3|F4|F5|F6|F7|F8|F9|F10|F11|F12
Gui, KeyInput:Add, Text, xm vHotkeyPreview, 快捷键预览:
Gui, KeyInput:Add, Button, default gSaveStartTriggerKey, 确定
Gui, KeyInput:Show
return
UpdateHotkeyPreview:
Gui, KeyInput:Submit, NoHide
newKey := ""
if (UseCtrl)
newKey .= "^"
if (UseAlt)
newKey .= "!"
if (UseWin)
newKey .= "#"
if (HotkeyChoice != "")
newKey .= HotkeyChoice
GuiControl, KeyInput:, HotkeyPreview, 快捷键预览: %newKey%
LogMessage("UpdateHotkeyPreview: newKey=" newKey)
return
SaveStartTriggerKey:
Gui, KeyInput:Submit
newKey := ""
if (UseCtrl)
newKey .= "^"
if (UseAlt)
newKey .= "!"
if (UseWin)
newKey .= "#"
if (HotkeyChoice != "")
newKey .= HotkeyChoice
else {
MsgBox, 请选择一个按键!
Gui, KeyInput:Show
return
}
if (newKey = "") {
MsgBox, 请至少选择一个修饰键或按键!
Gui, KeyInput:Show
return
}
if (newKey = NextTriggerKey || newKey = ToggleGuiKey) {
MsgBox, 此快捷键已被其他功能使用,请选择其他组合!
Gui, KeyInput:Show
return
}
if (StartTriggerKey != "") {
try {
Hotkey, %StartTriggerKey%, Off
StartTriggerKeyStatus := "未绑定"
LogMessage("释放旧 StartTriggerKey: " StartTriggerKey " 成功")
} catch e {
LogMessage("释放旧 StartTriggerKey: " StartTriggerKey " 失败: " e)
}
}
StartTriggerKey := newKey
IniWrite, %StartTriggerKey%, %TyporaConfigFile%, Hotkeys, StartTriggerKey
if (StartTriggerMode = 0) {
try {
Hotkey, %StartTriggerKey%, RunTypora
StartTriggerKeyStatus := "已绑定"
LogMessage("StartTriggerKey 更新为: " StartTriggerKey " 并绑定成功")
} catch e {
MsgBox, 快捷键 %StartTriggerKey% 无效,默认恢复为 1。错误: %e%
StartTriggerKey := "1"
StartTriggerKeyStatus := "恢复默认"
IniWrite, %StartTriggerKey%, %TyporaConfigFile%, Hotkeys, StartTriggerKey
Hotkey, %StartTriggerKey%, RunTypora
LogMessage("恢复默认 StartTriggerKey: " StartTriggerKey " 错误: " e)
}
}
Gui, KeyInput:Destroy
Gui, Main:Destroy
Gosub, CreateMainGui
MsgBox, 被触发快捷键已更新为: %StartTriggerKey%
return
; --- 设置 Next Trigger 快捷键 ---
SetNextTriggerKey:
Gui, KeyInput:New, +AlwaysOnTop
Gui, KeyInput:Add, CheckBox, vUseCtrl gUpdateHotkeyPreview, 使用 Ctrl
Gui, KeyInput:Add, CheckBox, vUseAlt gUpdateHotkeyPreview xm, 使用 Alt
Gui, KeyInput:Add, CheckBox, vUseWin gUpdateHotkeyPreview xm, 使用 Win
Gui, KeyInput:Add, Text, xm, 选择按键:
Gui, KeyInput:Add, DropDownList, vHotkeyChoice gUpdateHotkeyPreview, A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|F1|F2|F3|F4|F5|F6|F7|F8|F9|F10|F11|F12
Gui, KeyInput:Add, Text, xm vHotkeyPreview, 快捷键预览:
Gui, KeyInput:Add, Button, default gSaveNextTriggerKey, 确定
Gui, KeyInput:Show
return
SaveNextTriggerKey:
Gui, KeyInput:Submit
newKey := ""
if (UseCtrl)
newKey .= "^"
if (UseAlt)
newKey .= "!"
if (UseWin)
newKey .= "#"
if (HotkeyChoice != "")
newKey .= HotkeyChoice
else {
MsgBox, 请选择一个按键!
Gui, KeyInput:Show
return
}
if (newKey = "") {
MsgBox, 请至少选择一个修饰键或按键!
Gui, KeyInput:Show
return
}
if (newKey = StartTriggerKey || newKey = ToggleGuiKey) {
MsgBox, 此快捷键已被其他功能使用,请选择其他组合!
Gui, KeyInput:Show
return
}
NextTriggerKey := newKey
NextTriggerKeyStatus := "已设置"
IniWrite, %NextTriggerKey%, %TyporaConfigFile%, Hotkeys, NextTriggerKey
Gui, KeyInput:Destroy
Gui, Main:Destroy
Gosub, CreateMainGui
MsgBox, 下一触发快捷键已更新为: %NextTriggerKey%
return
; --- 设置 Toggle GUI 快捷键 ---
SetToggleGuiKey:
Gui, KeyInput:New, +AlwaysOnTop
Gui, KeyInput:Add, CheckBox, vUseCtrl gUpdateHotkeyPreview, 使用 Ctrl
Gui, KeyInput:Add, CheckBox, vUseAlt gUpdateHotkeyPreview xm, 使用 Alt
Gui, KeyInput:Add, CheckBox, vUseWin gUpdateHotkeyPreview xm, 使用 Win
Gui, KeyInput:Add, Text, xm, 选择按键:
Gui, KeyInput:Add, DropDownList, vHotkeyChoice gUpdateHotkeyPreview, A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|F1|F2|F3|F4|F5|F6|F7|F8|F9|F10|F11|F12
Gui, KeyInput:Add, Text, xm vHotkeyPreview, 快捷键预览:
Gui, KeyInput:Add, Button, default gSaveToggleGuiKey, 确定
Gui, KeyInput:Show
return
SaveToggleGuiKey:
Gui, KeyInput:Submit
newKey := ""
if (UseCtrl)
newKey .= "^"
if (UseAlt)
newKey .= "!"
if (UseWin)
newKey .= "#"
if (HotkeyChoice != "")
newKey .= HotkeyChoice
else {
MsgBox, 请选择一个按键!
Gui, KeyInput:Show
return
}
if (newKey = "") {
MsgBox, 请至少选择一个修饰键或按键!
Gui, KeyInput:Show
return
}
if (newKey = StartTriggerKey || newKey = NextTriggerKey) {
MsgBox, 此快捷键已被其他功能使用,请选择其他组合!
Gui, KeyInput:Show
return
}
if (ToggleGuiKey != "") {
try {
Hotkey, %ToggleGuiKey%, Off
ToggleGuiKeyStatus := "未绑定"
LogMessage("释放旧 ToggleGuiKey: " ToggleGuiKey " 成功")
} catch e {
LogMessage("释放旧 ToggleGuiKey: " ToggleGuiKey " 失败: " e)
}
}
ToggleGuiKey := newKey
IsToggleGuiKeyCustomized := 1
IniWrite, %ToggleGuiKey%, %TyporaConfigFile%, Hotkeys, ToggleGuiKey
IniWrite, %IsToggleGuiKeyCustomized%, %TyporaConfigFile%, Hotkeys, IsToggleGuiKeyCustomized
try {
Hotkey, %ToggleGuiKey%, ToggleGui
ToggleGuiKeyStatus := "已绑定"
LogMessage("ToggleGuiKey 更新为: " ToggleGuiKey " 并绑定成功")
} catch e {
MsgBox, 快捷键 %ToggleGuiKey% 无效,默认恢复为 Win+T。错误: %e%
ToggleGuiKey := "#t"
ToggleGuiKeyStatus := "恢复默认"
IsToggleGuiKeyCustomized := 0
IniWrite, %ToggleGuiKey%, %TyporaConfigFile%, Hotkeys, ToggleGuiKey
IniWrite, %IsToggleGuiKeyCustomized%, %TyporaConfigFile%, Hotkeys, IsToggleGuiKeyCustomized
Hotkey, %ToggleGuiKey%, ToggleGui
LogMessage("恢复默认 ToggleGuiKey: " ToggleGuiKey " 错误: " e)
}
Gui, KeyInput:Destroy
Gui, Main:Destroy
Gosub, CreateMainGui
MsgBox, 显示/隐藏 GUI 快捷键已更新为: %ToggleGuiKey%
return
; --- 运行 Typora ---
RunTypora:
Gui, Main:Submit, NoHide
IniRead, RemainingFiles, %RemainingFilesConfig%, Settings, RemainingFiles, 0
if (!IsTyporaMonitoring) {
MsgBox, 笔记监控未启用,请先开始监控!
LogMessage("RunTypora: 笔记监控未启用")
return
}
if (MainFolder = "") {
MsgBox, 请先选择主文件夹!
LogMessage("主文件夹未选择")
return
}
if (SubFolder = "") {
SaveFolder := MainFolder
} else {
SaveFolder := MainFolder "\" SubFolder
}
if !FileExist(SaveFolder) {
MsgBox, 保存文件夹不存在!
LogMessage("保存文件夹不存在: " SaveFolder)
return
}
if (UseRecordedName) {
IniRead, fileName, %CurrentFileConfig%, CurrentFile, Name
if (fileName = "" || fileName = "ERROR") {
MsgBox, 无法读取文件名,请手动输入。
InputBox, fileName, 输入文件名, 请输入文件名(不含扩展名):, , 300, 150
if (fileName = "") {
MsgBox, 未输入文件名,操作取消。
LogMessage("未输入文件名")
return
}
}
} else {
InputBox, fileName, 输入文件名, 请输入文件名(不含扩展名):, , 300, 150
if (fileName = "") {
MsgBox, 未输入文件名,操作取消。
LogMessage("未输入文件名")
return
}
}
LogMessage("最终文件名: " fileName)
MouseMove, %ClickPos1X%, %ClickPos1Y%, 0
Sleep, 200
Click
Sleep, 1000
MouseMove, %ClickPos2X%, %ClickPos2Y%, 0
Sleep, 200
Click
Sleep, 500
LogMessage("模拟点击完成")
Run, "%TyporaPath%" "%SaveFolder%", , UseErrorLevel
if (ErrorLevel) {
MsgBox, 无法启动 Typora!
LogMessage("Typora 启动失败")
return
}
WinWait, ahk_exe typora.exe, , 5
WinActivate, ahk_exe typora.exe
WinWaitActive, ahk_exe typora.exe, , 5
Sleep, 2000
LogMessage("Typora 启动并激活")
Send {F11}
Sleep, 1500
Send ^v
Sleep, 2000
Send ^s
Sleep, 2000
Clipboard := fileName
Send ^v
Sleep, 1000
Send {Enter}
Sleep, 1000
Send ^s
Sleep, 1000
Send !{F4}
Sleep, 500
LogMessage("Typora 操作完成")
SavedFilePath := SaveFolder "\" fileName ".md"
if FileExist(SavedFilePath) {
IniDelete, %CurrentFileConfig%, CurrentFile, Name
IniRead, RemainingFiles, %RemainingFilesConfig%, Settings, RemainingFiles, 0
LogMessage("笔记保存成功: " SavedFilePath)
; 重置 ReadyForNote 标志位
IniWrite, 0, %SignalFile%, Signals, ReadyForNote
LogMessage("重置 ReadyForNote=0")
if (AutoTriggerNext && RemainingFiles > 0) {
if (NextTriggerMode = 0) {
sendKey := ConvertHotkeyToSendFormat(NextTriggerKey)
Send %sendKey%
Sleep, 100
LogMessage("发送下一触发快捷键: " NextTriggerKey)
} else {
ToolTip, 设置信号量 %SignalNextName%=1
Sleep, 1000
ToolTip
IniWrite, 1, %SignalFile%, Signals, %SignalNextName%
Sleep, 100
LogMessage("设置信号量 " SignalNextName "=1")
}
}
} else {
MsgBox, 笔记 %fileName% 保存失败!
LogMessage("笔记保存失败: " SavedFilePath)
}
Gui, Main:Destroy
Gosub, CreateMainGui
return
; --- 处理 GUI 关闭 ---
GuiClose:
Gui, Main:Hide
GuiVisible := 0
IniWrite, %GuiVisible%, %TyporaConfigFile%, Settings, GuiVisible
LogMessage("GUI 关闭")
return
; --- 初始化 ---
Gosub, CreateMainGui
Gosub, CreateFloatWindow
BindHotkeys() ; 自动绑定快捷键
if (IsTyporaMonitoring) {
SetTimer, UpdateCountdown, 1000
LogMessage("脚本启动时恢复监控")
}
LogMessage("脚本启动完成")
return
; --- 退出脚本 ---
OnExit:
SetTimer, UpdateCountdown, Off
Gui, Float:Destroy
LogMessage("脚本退出")
ExitApp
return