├── .github └── ISSUE_TEMPLATE │ └── new-version-available.md ├── .gitignore ├── AHK ├── Compile.ahk ├── EnableUIAccess2AHK.ahk ├── Lib │ ├── Cert.ahk │ ├── Crypt.ahk │ ├── SignFile.ahk │ └── SystemTime.ahk └── Setup.ahk ├── OneQuick Launcher.ahk ├── README.md ├── icon ├── 1.ico ├── 2.ico ├── 3.ico └── 4.ico ├── lang ├── cn.ini └── en.ini ├── script ├── JSON.ahk ├── OneQuick.Core.ahk ├── OneQuick.ahk ├── OneQuick.feature.default.yaml ├── OneQuick.setting.default.yaml ├── Yaml.ahk ├── update_list.json ├── user_guide.ahk └── version.yaml ├── tool └── ABOUT.txt └── 安装说明.txt /.github/ISSUE_TEMPLATE/new-version-available.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: New Version Available 3 | about: New Version Available 4 | 5 | --- 6 | 7 | AHK版已停止更新,请使用新版 https://onequick.org/ 8 | 微软应用商店搜索OneQuick即可获得 9 | New Version available in Microsoft Store! 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /_bkp 2 | /archive 3 | /data 4 | /tool 5 | !/tool/ABOUT.txt 6 | 7 | *.rar 8 | *.zip 9 | *.bat 10 | *.exe 11 | *.lnk 12 | 13 | config.ini 14 | OneQuick.Ext.ahk 15 | OneQuick.feature.yaml 16 | -------------------------------------------------------------------------------- /AHK/Compile.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | @author: XJK 3 | @github: https://github.com/XUJINKAI/OneQuick 4 | */ 5 | 6 | compile_ahk(target, icon="") 7 | { 8 | splitpath, a_ahkpath, , ahk_dir 9 | Ahk2Exe := ahk_dir "\Compiler\Ahk2Exe.exe" 10 | u32bin := ahk_dir "\Compiler\Unicode 32-bit.bin" 11 | if not FileExist(Ahk2Exe) 12 | MsgBox, can't find Compiler\Ahk2Exe.exe 13 | else if not FileExist(u32bin) 14 | MsgBox, can't find Compiler\Unicode 32-bit.bin 15 | Else 16 | { 17 | if(icon=="") { 18 | run, %Ahk2Exe% /in "%target%" /bin "%u32bin%" 19 | } 20 | else { 21 | run, %Ahk2Exe% /in "%target%" /icon "%icon%" /bin "%u32bin%" 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /AHK/EnableUIAccess2AHK.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | EnableUIAccess.ahk v1.01 by Lexikos 3 | 4 | USE AT YOUR OWN RISK 5 | 6 | Enables the uiAccess flag in an application's embedded manifest 7 | and signs the file with a self-signed digital certificate. If the 8 | file is in a trusted location (A_ProgramFiles or A_WinDir), this 9 | allows the application to bypass UIPI (User Interface Privilege 10 | Isolation, a part of User Account Control in Vista/7). It also 11 | enables the journal playback hook (SendPlay). 12 | 13 | Command line params (mutually exclusive): 14 | JK:自动修改autohotkey.exe 15 | //SkipWarning - don't display the initial warning 16 | //"" "" - attempt to run silently using the given file(s) 17 | 18 | This script and the provided Lib files may be used, modified, 19 | copied, etc. without restriction. 20 | 21 | */ 22 | 23 | #NoEnv 24 | 25 | #Include 26 | #Include 27 | #Include 28 | #Include 29 | 30 | ; Command line args: 31 | ; JK 对ahk.exe 32 | para1 = %1% 33 | silent := para1=="/S" 34 | 35 | m(msg) 36 | { 37 | if(silent) { 38 | return 39 | } 40 | msgbox ,,OneQuick, % msg 41 | } 42 | 43 | in_file := A_AhkPath 44 | out_file := A_AhkPath 45 | 46 | if Crypt.IsSigned(in_file) 47 | { 48 | ; JK 49 | m("Already enabled.") 50 | ExitApp 51 | } 52 | 53 | ; if (in_file = "") 54 | ; MsgBox 49,, 55 | ; (Join 56 | ; This script enables the selected AutoHotkey.exe to bypass restrictions 57 | ; imposed by UIPI, a component of UAC in Windows Vista and 7. To do this 58 | ; it modifies an attribute in the file's embedded manifest and signs the 59 | ; file using a self-signed digital certificate, which is then installed 60 | ; in the local machine's Trusted Root Certification Authorities store.`n 61 | ; `n 62 | ; THE RESULTING EXECUTABLE MAY BE UNUSABLE ON ANY SYSTEM WHERE THIS 63 | ; CERTIFICATE IS NOT INSTALLED.`n 64 | ; `n 65 | ; Continue at your own risk. 66 | ; ) 67 | if(!silent) 68 | { 69 | MsgBox 49,, 70 | ( 71 | 启用UIAccess可以让OneQuick对管理员权限程序起作用, 72 | 以后如果要卸载Autohotkey,可以运行AutoHotkey_Install.exe选择卸载选项。 73 | ) 74 | ifMsgBox Cancel 75 | ExitApp 76 | } 77 | 78 | if !A_IsAdmin 79 | { 80 | if (in_file = "") 81 | in_file := "SkipWarning" 82 | cmd = "%A_ScriptFullPath%" 83 | if !A_IsCompiled 84 | { ; Use A_AhkPath in case the "runas" verb isn't registered for ahk files. 85 | cmd = "%A_AhkPath%" %cmd% 86 | } 87 | Run *RunAs %cmd% "RUNAS",, UseErrorLevel 88 | ExitApp 89 | } 90 | 91 | if (in_file = "" || in_file = "SkipWarning") 92 | { 93 | ; Find AutoHotkey installation. 94 | RegRead InstallDir, HKEY_LOCAL_MACHINE, SOFTWARE\AutoHotkey, InstallDir 95 | if ErrorLevel && A_PtrSize=8 96 | RegRead InstallDir, HKLM, SOFTWARE\Wow6432Node\AutoHotkey, InstallDir 97 | 98 | ; Let user confirm or select file(s). 99 | FileSelectFile in_file, 1, %InstallDir%\AutoHotkey.exe 100 | , Select Source File, Executable Files (*.exe) 101 | if ErrorLevel 102 | ExitApp 103 | FileSelectFile out_file, S16, %in_file% 104 | , Select Destination File, Executable Files (*.exe) 105 | if ErrorLevel 106 | ExitApp 107 | user_specified_files := true 108 | } 109 | 110 | ; Convert short paths to long paths. 111 | Loop %in_file%, 0 112 | in_file := A_LoopFileLongPath 113 | if (out_file = "") ; i.e. only one file was given via command line. 114 | out_file := in_file 115 | else 116 | Loop %out_file%, 0 117 | out_file := A_LoopFileLongPath 118 | 119 | if Crypt.IsSigned(in_file) 120 | { 121 | ; JK 122 | m("UIAccess enabled.") 123 | ExitApp 124 | } 125 | 126 | if user_specified_files && !IsTrustedLocation(out_file) 127 | { 128 | MsgBox 49,, 129 | (LTrim Join`s 130 | The path you have selected is not a trusted location. If you choose 131 | to continue, the uiAccess attribute will be set but will not have 132 | any effect until the file is moved to a trusted location. Trusted 133 | locations include \Program Files\ and \Windows\System32\. 134 | ) 135 | ifMsgBox Cancel 136 | ExitApp 137 | } 138 | 139 | if (in_file = out_file) 140 | { 141 | ; The following should typically work even if the file is in use: 142 | bak_file := in_file "~" A_Now ".bak" 143 | FileMove %in_file%, %bak_file%, 1 144 | if ErrorLevel 145 | Fail("Failed to rename selected file.") 146 | in_file := bak_file 147 | } 148 | FileCopy %in_file%, %out_file%, 1 149 | if ErrorLevel 150 | Fail("Failed to copy file to destination.") 151 | 152 | 153 | ; Set the uiAccess attribute in the file's manifest to "true". 154 | if !EXE_uiAccess_set(out_file, true) 155 | Fail("Failed to set uiAccess attribute in manifest.") 156 | 157 | 158 | ; Open the current user's "Personal" certificate store. 159 | my := Cert.OpenStore(Cert.STORE_PROV_SYSTEM, 0, Cert.SYSTEM_STORE_CURRENT_USER, "wstr", "My") 160 | if !my 161 | Warn("Failed to open 'Personal' certificate store.") 162 | 163 | ; Locate "AutoHotkey" certificate created by a previous run of this script. 164 | ahk_cert := my.FindCertificates(0, Cert.FIND_SUBJECT_STR, "wstr", "AutoHotkey")[1] 165 | 166 | if !ahk_cert 167 | { 168 | ; Create key container. 169 | cr := Crypt.AcquireContext("AutoHotkey", 0, Crypt.PROV_RSA_FULL, Crypt.NEWKEYSET) 170 | if !cr 171 | Fail("Failed to create 'AutoHotkey' key container.") 172 | 173 | ; Generate key for certificate. 174 | key := cr.GenerateKey(Crypt.AT_SIGNATURE, 1024, Crypt.EXPORTABLE) 175 | 176 | ; Create simple certificate name. 177 | cn := new Cert.Name({CommonName: "AutoHotkey"}) 178 | 179 | ; Set end time to 10 years from now. 180 | end_time := SystemTime.Now() 181 | end_time.Year += 10 182 | 183 | ; Create certificate using the parameters created above. 184 | ahk_cert := cr.CreateSelfSignCertificate(cn, 0, end_time) 185 | if !ahk_cert 186 | Fail("Failed to create 'AutoHotkey' certificate.") 187 | 188 | ; Add certificate to current user's "Personal" store so they won't 189 | ; need to create it again if they need to update the executable. 190 | if !(my.AddCertificate(ahk_cert, Cert.STORE_ADD_NEW)) 191 | Warn("Failed to add certificate to 'Personal' store.") 192 | ; Proceed even if above failed, since it probably doesn't matter. 193 | 194 | ; Attempt to install certificate in trusted store. 195 | root := Cert.OpenStore(Cert.STORE_PROV_SYSTEM, 0, Cert.SYSTEM_STORE_LOCAL_MACHINE, "wstr", "Root") 196 | if !(root && root.AddCertificate(ahk_cert, Cert.STORE_ADD_USE_EXISTING)) 197 | { 198 | if (%True% != "Silent") 199 | MsgBox 49,, 200 | (LTrim Join`s 201 | Failed to install certificate. If you continue, the executable 202 | may become unusable until the certificate is manually installed. 203 | This can typically be done via Digital Signatures tab on the 204 | file's Properties dialog. 205 | ) 206 | ifMsgBox Cancel 207 | ExitApp 208 | } 209 | 210 | key.Dispose() 211 | cr.Dispose() 212 | } 213 | 214 | ; Sign the file. 215 | if !SignFile(out_file, ahk_cert, "AutoHotkey") 216 | Fail("Failed to sign file.") 217 | 218 | 219 | ; In interactive mode, if not overwriting the original file, offer 220 | ; to create an additional context menu item for AHK files. 221 | if (user_specified_files && in_file != out_file) 222 | { 223 | RegRead uiAccessVerb, HKCR, AutoHotkeyScript\Shell\uiAccess\Command 224 | if ErrorLevel 225 | { 226 | MsgBox 3,, Register "Run Script with UI Access" context menu item? 227 | ifMsgBox Yes 228 | { 229 | RegWrite REG_SZ, HKCR, AutoHotkeyScript\Shell\uiAccess 230 | ,, Run with UI Access 231 | RegWrite REG_SZ, HKCR, AutoHotkeyScript\Shell\uiAccess\Command 232 | ,, "%out_file%" "`%1" `%* 233 | } 234 | ifMsgBox Cancel 235 | ExitApp 236 | } 237 | } 238 | 239 | 240 | ; IsTrustedLocation 241 | ; Returns true if path is a valid location for uiAccess="true". 242 | IsTrustedLocation(path) 243 | { 244 | ; http://msdn.microsoft.com/en-us/library/bb756929 245 | ; MSDN: "\Program Files\ and \windows\system32\ are currently the 246 | ; two allowable protected locations." 247 | ; However, \Program Files (x86)\ also appears to be allowed. 248 | if InStr(path, A_ProgramFiles "\") = 1 249 | return true 250 | if InStr(path, A_WinDir "\System32\") = 1 251 | return true 252 | 253 | ; On 64-bit systems, if this script is 32-bit, A_ProgramFiles is 254 | ; %ProgramFiles(x86)%, otherwise it is %ProgramW6432%. So check 255 | ; the opposite "Program Files" folder: 256 | EnvGet other, % A_PtrSize=8 ? "ProgramFiles(x86)" : "ProgramW6432" 257 | if (other != "" && InStr(path, other "\") = 1) 258 | return true 259 | 260 | return false 261 | } 262 | 263 | 264 | ; EXE_uiAccess_set 265 | ; Sets the uiAccess attribute in an executable file's manifest. 266 | ; file - Path of file. 267 | ; value - New value; must be boolean (0 or 1). 268 | EXE_uiAccess_set(file, value) 269 | { 270 | ; Load manifest from EXE file. 271 | xml := ComObjCreate("Msxml2.DOMDocument") 272 | xml.async := false 273 | xml.setProperty("SelectionLanguage", "XPath") 274 | xml.setProperty("SelectionNamespaces" 275 | , "xmlns:v1='urn:schemas-microsoft-com:asm.v1' " 276 | . "xmlns:v3='urn:schemas-microsoft-com:asm.v3'") 277 | if !xml.load("res://" file "/#24/#1") 278 | { 279 | ; This will happen if the file doesn't exist or can't be opened, 280 | ; or if it doesn't have an embedded manifest. 281 | ErrorLevel := "load" 282 | return false 283 | } 284 | 285 | ; Check if any change is necessary. If the uiAccess attribute is 286 | ; not present, it is effectively "false": 287 | node := xml.selectSingleNode("/v1:assembly/v3:trustInfo/security" 288 | . "/requestedPrivileges/requestedExecutionLevel") 289 | if ((node && node.getAttribute("uiAccess") = "true") = value) 290 | { 291 | ErrorLevel := "already set" 292 | return true 293 | } 294 | 295 | ; The follow "IF" section should be unnecessary for AutoHotkey_L. 296 | if !node 297 | { 298 | ; Get assembly node, which should always exist. 299 | if !last := xml.selectSingleNode("/v1:assembly") 300 | { 301 | ErrorLevel := "invalid manifest" 302 | return 0 303 | } 304 | for _, name in ["trustInfo", "security", "requestedPrivileges" 305 | , "requestedExecutionLevel"] 306 | { 307 | if !(node := last.selectSingleNode("*[local-name()='" name "']")) 308 | { 309 | static NODE_ELEMENT := 1 310 | node := xml.createNode(NODE_ELEMENT, name 311 | , "urn:schemas-microsoft-com:asm.v3") 312 | last.appendChild(node) 313 | } 314 | last := node 315 | } 316 | ; Since the requestedExecutionLevel node didn't exist before, 317 | ; we must have just created it. Although this attribute *might* 318 | ; not actually be required, it seems best to set it: 319 | node.setAttribute("level", "asInvoker") 320 | } 321 | 322 | ; Set the uiAccess attribute! 323 | node.setAttribute("uiAccess", value ? "true" : "false") 324 | 325 | ; Retrieve XML text. 326 | xml := RTrim(xml.xml, "`r`n") 327 | 328 | ; Convert to UTF-8. 329 | VarSetCapacity(data, data_size := StrPut(xml, "utf-8") - 1) 330 | StrPut(xml, &data, "utf-8") 331 | 332 | ; 333 | ; Replace manifest resource. 334 | ; 335 | 336 | hupd := DllCall("BeginUpdateResource", "str", file, "int", false) 337 | if !hupd 338 | { 339 | ErrorLevel := "BeginUpdateResource" 340 | return false 341 | } 342 | 343 | ; Res type RT_MANIFEST (24), resource ID 1, language English (US) 344 | r := DllCall("UpdateResource", "ptr", hupd, "ptr", 24, "ptr", 1 345 | , "ushort", 1033, "ptr", &data, "uint", data_size) 346 | 347 | if !DllCall("EndUpdateResource", "ptr", hupd, "int", !r) 348 | { 349 | ErrorLevel := "EndUpdateResource" 350 | return false 351 | } 352 | if !r ; i.e. above succeeded only in discarding the failed changes. 353 | { 354 | ErrorLevel := "UpdateResource" 355 | return false 356 | } 357 | ; Success! 358 | ErrorLevel := 0 359 | return true 360 | } 361 | 362 | 363 | Fail(msg) 364 | { 365 | if (%True% != "Silent") 366 | MsgBox 16,, %msg%`n`nErrorLevel: %ErrorLevel%`nA_LastError: %A_LastError% 367 | ExitApp 368 | } 369 | 370 | Warn(msg) 371 | { 372 | msg .= " (Err " ErrorLevel "; " A_LastError ")`n" 373 | OutputDebug %msg% 374 | FileAppend %msg%, * 375 | } -------------------------------------------------------------------------------- /AHK/Lib/Cert.ahk: -------------------------------------------------------------------------------- 1 | class Cert 2 | { 3 | ; Encoding Types 4 | static X509_ASN_ENCODING := 0x00000001 5 | , PKCS_7_ASN_ENCODING := 0x00010000 6 | 7 | ; Certificate Information Flags (CERT_INFO_*) 8 | static INFO_VERSION_FLAG := 1 9 | , INFO_SERIAL_NUMBER_FLAG := 2 10 | , INFO_SIGNATURE_ALGORITHM_FLAG := 3 11 | , INFO_ISSUER_FLAG := 4 12 | , INFO_NOT_BEFORE_FLAG := 5 13 | , INFO_NOT_AFTER_FLAG := 6 14 | , INFO_SUBJECT_FLAG := 7 15 | , INFO_SUBJECT_PUBLIC_KEY_INFO_FLAG := 8 16 | , INFO_ISSUER_UNIQUE_ID_FLAG := 9 17 | , INFO_SUBJECT_UNIQUE_ID_FLAG := 10 18 | , INFO_EXTENSION_FLAG := 11 19 | 20 | ; Certificate Comparison Functions (CERT_COMPARE_*) 21 | static COMPARE_MASK := 0xFFFF 22 | , COMPARE_SHIFT := (_ := 16) 23 | , COMPARE_ANY := 0 24 | , COMPARE_SHA1_HASH := 1 25 | , COMPARE_NAME := 2 26 | , COMPARE_ATTR := 3 27 | , COMPARE_MD5_HASH := 4 28 | , COMPARE_PROPERTY := 5 29 | , COMPARE_PUBLIC_KEY := 6 30 | , COMPARE_HASH := Cert.COMPARE_SHA1_HASH 31 | , COMPARE_NAME_STR_A := 7 32 | , COMPARE_NAME_STR_W := 8 33 | , COMPARE_KEY_SPEC := 9 34 | , COMPARE_ENHKEY_USAGE := 10 35 | , COMPARE_CTL_USAGE := Cert.COMPARE_ENHKEY_USAGE 36 | , COMPARE_SUBJECT_CERT := 11 37 | , COMPARE_ISSUER_OF := 12 38 | , COMPARE_EXISTING := 13 39 | , COMPARE_SIGNATURE_HASH := 14 40 | , COMPARE_KEY_IDENTIFIER := 15 41 | , COMPARE_CERT_ID := 16 42 | , COMPARE_CROSS_CERT_DIST_POINTS := 17 43 | , COMPARE_PUBKEY_MD5_HASH := 18 44 | , COMPARE_SUBJECT_INFO_ACCESS := 19 45 | 46 | ; dwFindType Flags (CERT_FIND_*) 47 | static FIND_ANY := Cert.COMPARE_ANY << _ 48 | , FIND_SHA1_HASH := Cert.COMPARE_SHA1_HASH << _ 49 | , FIND_MD5_HASH := Cert.COMPARE_MD5_HASH << _ 50 | , FIND_SIGNATURE_HASH := Cert.COMPARE_SIGNATURE_HASH << _ 51 | , FIND_KEY_IDENTIFIER := Cert.COMPARE_KEY_IDENTIFIER << _ 52 | , FIND_HASH := Cert.FIND_SHA1_HASH 53 | , FIND_PROPERTY := Cert.COMPARE_PROPERTY << _ 54 | , FIND_PUBLIC_KEY := Cert.COMPARE_PUBLIC_KEY << _ 55 | , FIND_SUBJECT_NAME := (Cert.COMPARE_NAME << _) | Cert.INFO_SUBJECT_FLAG 56 | , FIND_SUBJECT_ATTR := (Cert.COMPARE_ATTR << _) | Cert.INFO_SUBJECT_FLAG 57 | , FIND_ISSUER_NAME := (Cert.COMPARE_NAME << _) | Cert.INFO_ISSUER_FLAG 58 | , FIND_ISSUER_ATTR := (Cert.COMPARE_ATTR << _) | Cert.INFO_ISSUER_FLAG 59 | , FIND_SUBJECT_STR := (Cert.COMPARE_NAME_STR_W << _) | Cert.INFO_SUBJECT_FLAG 60 | , FIND_ISSUER_STR := (Cert.COMPARE_NAME_STR_W << _) | Cert.INFO_ISSUER_FLAG 61 | , FIND_KEY_SPEC := Cert.COMPARE_KEY_SPEC << _ 62 | , FIND_ENHKEY_USAGE := Cert.COMPARE_ENHKEY_USAGE << _ 63 | , FIND_CTL_USAGE := Cert.FIND_ENHKEY_USAGE 64 | , FIND_SUBJECT_CERT := Cert.COMPARE_SUBJECT_CERT << _ 65 | , FIND_ISSUER_OF := Cert.COMPARE_ISSUER_OF << _ 66 | , FIND_EXISTING := Cert.COMPARE_EXISTING << _ 67 | , FIND_CERT_ID := Cert.COMPARE_CERT_ID << _ 68 | , FIND_CROSS_CERT_DIST_POINTS := Cert.COMPARE_CROSS_CERT_DIST_POINTS << _ 69 | , FIND_PUBKEY_MD5_HASH := Cert.COMPARE_PUBKEY_MD5_HASH << _ 70 | , FIND_SUBJECT_INFO_ACCESS := Cert.COMPARE_SUBJECT_INFO_ACCESS << _ 71 | 72 | ; Certificate Store Provider Types (CERT_STORE_PROV_*) 73 | static STORE_PROV_MSG := 1 74 | , STORE_PROV_MEMORY := 2 75 | , STORE_PROV_FILE := 3 76 | , STORE_PROV_REG := 4 77 | , STORE_PROV_PKCS7 := 5 78 | , STORE_PROV_SERIALIZED := 6 79 | , STORE_PROV_FILENAME_A := 7 80 | , STORE_PROV_FILENAME_W := 8 81 | , STORE_PROV_FILENAME := Cert.STORE_PROV_FILENAME_W 82 | , STORE_PROV_SYSTEM_A := 9 83 | , STORE_PROV_SYSTEM_W := 10 84 | , STORE_PROV_SYSTEM := Cert.STORE_PROV_SYSTEM_W 85 | , STORE_PROV_COLLECTION := 11 86 | , STORE_PROV_SYSTEM_REGISTRY_A := 12 87 | , STORE_PROV_SYSTEM_REGISTRY_W := 13 88 | , STORE_PROV_SYSTEM_REGISTRY := Cert.STORE_PROV_SYSTEM_REGISTRY_W 89 | , STORE_PROV_PHYSICAL_W := 14 90 | , STORE_PROV_PHYSICAL := Cert.STORE_PROV_PHYSICAL_W 91 | , STORE_PROV_LDAP_W := 16 92 | , STORE_PROV_LDAP := Cert.STORE_PROV_LDAP_W 93 | , STORE_PROV_PKCS12 := 17 94 | 95 | ; Certificate Store open/property flags (low-word; CERT_STORE_*) 96 | static STORE_NO_CRYPT_RELEASE_FLAG := 0x0001 97 | , STORE_SET_LOCALIZED_NAME_FLAG := 0x0002 98 | , STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG := 0x0004 99 | , STORE_DELETE_FLAG := 0x0010 100 | , STORE_UNSAFE_PHYSICAL_FLAG := 0x0020 101 | , STORE_SHARE_STORE_FLAG := 0x0040 102 | , STORE_SHARE_CONTEXT_FLAG := 0x0080 103 | , STORE_MANIFOLD_FLAG := 0x0100 104 | , STORE_ENUM_ARCHIVED_FLAG := 0x0200 105 | , STORE_UPDATE_KEYID_FLAG := 0x0400 106 | , STORE_BACKUP_RESTORE_FLAG := 0x0800 107 | , STORE_READONLY_FLAG := 0x8000 108 | , STORE_OPEN_EXISTING_FLAG := 0x4000 109 | , STORE_CREATE_NEW_FLAG := 0x2000 110 | , STORE_MAXIMUM_ALLOWED_FLAG := 0x1000 111 | 112 | ; Certificate System Store Flag Values (high-word; CERT_SYSTEM_STORE_*) 113 | static SYSTEM_STORE_MASK := 0xFFFF0000 114 | , SYSTEM_STORE_RELOCATE_FLAG := 0x80000000 115 | , SYSTEM_STORE_UNPROTECTED_FLAG := 0x40000000 116 | ; Location of the system store: 117 | , SYSTEM_STORE_LOCATION_MASK := 0x00FF0000 118 | , SYSTEM_STORE_LOCATION_SHIFT := (_ := 16) 119 | ; Registry: HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE 120 | , SYSTEM_STORE_CURRENT_USER_ID := 1 121 | , SYSTEM_STORE_LOCAL_MACHINE_ID := 2 122 | ; Registry: HKEY_LOCAL_MACHINE\Software\Microsoft\Cryptography\Services 123 | , SYSTEM_STORE_CURRENT_SERVICE_ID := 4 124 | , SYSTEM_STORE_SERVICES_ID := 5 125 | ; Registry: HKEY_USERS 126 | , SYSTEM_STORE_USERS_ID := 6 127 | ; Registry: HKEY_CURRENT_USER\Software\Policies\Microsoft\SystemCertificates 128 | , SYSTEM_STORE_CURRENT_USER_GROUP_POLICY_ID := 7 129 | ; Registry: HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\SystemCertificates 130 | , SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY_ID := 8 131 | ; Registry: HKEY_LOCAL_MACHINE\Software\Microsoft\EnterpriseCertificates 132 | , SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE_ID := 9 133 | , SYSTEM_STORE_CURRENT_USER := (Cert.SYSTEM_STORE_CURRENT_USER_ID << _) 134 | , SYSTEM_STORE_LOCAL_MACHINE := (Cert.SYSTEM_STORE_LOCAL_MACHINE_ID << _) 135 | , SYSTEM_STORE_CURRENT_SERVICE := (Cert.SYSTEM_STORE_CURRENT_SERVICE_ID << _) 136 | , SYSTEM_STORE_SERVICES := (Cert.SYSTEM_STORE_SERVICES_ID << _) 137 | , SYSTEM_STORE_USERS := (Cert.SYSTEM_STORE_USERS_ID << _) 138 | , SYSTEM_STORE_CURRENT_USER_GROUP_POLICY := (Cert.SYSTEM_STORE_CURRENT_USER_GROUP_POLICY_ID << _) 139 | , SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY := (Cert.SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY_ID << _) 140 | , SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE := (Cert.SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE_ID << _) 141 | 142 | ; Certificate name types (CERT_NAME_*) 143 | static NAME_EMAIL_TYPE := 1 144 | , NAME_RDN_TYPE := 2 145 | , NAME_ATTR_TYPE := 3 146 | , NAME_SIMPLE_DISPLAY_TYPE := 4 147 | , NAME_FRIENDLY_DISPLAY_TYPE := 5 148 | , NAME_DNS_TYPE := 6 149 | , NAME_URL_TYPE := 7 150 | , NAME_UPN_TYPE := 8 151 | ; Certificate name flags 152 | , NAME_ISSUER_FLAG := 0x00000001 153 | , NAME_DISABLE_IE4_UTF8_FLAG := 0x00010000 154 | , NAME_STR_ENABLE_PUNYCODE_FLAG := 0x00200000 155 | 156 | ; dwAddDisposition values (CERT_STORE_ADD_*) 157 | static STORE_ADD_NEW := 1 158 | , STORE_ADD_USE_EXISTING := 2 159 | , STORE_ADD_REPLACE_EXISTING := 3 160 | , STORE_ADD_ALWAYS := 4 161 | , STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES := 5 162 | , STORE_ADD_NEWER := 6 163 | , STORE_ADD_NEWER_INHERIT_PROPERTIES := 7 164 | 165 | ; 166 | ; Static Methods 167 | ; 168 | 169 | OpenStore(pStoreProvider, dwMsgAndCertEncodingType, dwFlags, ParamType="Ptr", Param=0) 170 | { 171 | hCertStore := DllCall("Crypt32\CertOpenStore" 172 | , "ptr", pStoreProvider 173 | , "uint", dwMsgAndCertEncodingType 174 | , "ptr", 0 ; hCryptProv 175 | , "uint", dwFlags 176 | , ParamType, Param) 177 | if hCertStore 178 | hCertStore := new this.Store(hCertStore) 179 | return hCertStore 180 | } 181 | 182 | GetStoreNames(dwFlags) 183 | { 184 | static cb := RegisterCallback("Cert_GetStoreNames_Callback", "F") 185 | global Cert 186 | DllCall("Crypt32\CertEnumSystemStore", "uint", dwFlags 187 | , "ptr", 0, "ptr", &(names := []), "ptr", cb) 188 | return names 189 | } 190 | 191 | 192 | ; 193 | ; Certificate Name 194 | ; 195 | class Name 196 | { 197 | __New(Props) 198 | { 199 | static Fields := { 200 | (Join, 201 | CommonName: "CN" 202 | LocalityName: "L" 203 | Organization: "O" 204 | OrganizationalUnit: "OU" 205 | Email: "E" 206 | Country: "C" 207 | State: "ST" 208 | StreetAddress: "STREET" 209 | Title: "T" 210 | GivenName: "G" 211 | Initials: "I" 212 | Surname: "SN" 213 | Doman: "DC" 214 | )} 215 | static CERT_X500_NAME_STR := 3, Q := """" ; For readability. 216 | 217 | if IsObject(Props) 218 | { 219 | ; Build name string from caller-supplied object. 220 | name_string := "" 221 | for field_name, field_code in Fields 222 | { 223 | if Props.HasKey(field_name) 224 | { 225 | if (name_string != "") 226 | name_string .= ";" 227 | name_string .= field_code "=" Q RegExReplace(Props[field_name], Q, Q Q) Q 228 | } 229 | } 230 | } 231 | else 232 | name_string := Props 233 | 234 | Loop 2 235 | { 236 | if A_Index=1 237 | { ; First iteration: retrieve required size. 238 | pbEncoded := 0 239 | cbEncoded := 0 240 | } 241 | else 242 | { ; Second iteration: retrieve encoded name. 243 | this.SetCapacity("data", cbEncoded) 244 | pbEncoded := this.GetAddress("data") 245 | } 246 | global Cert 247 | if !DllCall("Crypt32\CertStrToName" 248 | , "uint", Cert.X509_ASN_ENCODING 249 | , "str", name_string 250 | , "uint", CERT_X500_NAME_STR 251 | , "ptr", 0 ; Reserved 252 | , "ptr", pbEncoded 253 | , "uint*", cbEncoded 254 | , "str*", ErrorString) 255 | { 256 | ErrorLevel := ErrorString 257 | return false 258 | } 259 | } 260 | this.SetCapacity("blob", A_PtrSize*2) ; CERT_NAME_BLOB 261 | NumPut(pbEncoded, NumPut(cbEncoded, this.p := this.GetAddress("blob"))) 262 | } 263 | } 264 | 265 | 266 | ; 267 | ; Certificate Store 268 | ; 269 | class Store 270 | { 271 | FindCertificates(dwFindFlags, dwFindType, FindParamType="ptr", FindParam=0) 272 | { 273 | global Cert 274 | hStore := this.h 275 | , dwCertEncodingType := Cert.X509_ASN_ENCODING | Cert.PKCS_7_ASN_ENCODING 276 | , ctx := new Cert.Context(0) 277 | , certs := [] 278 | while ctx.p := DllCall("Crypt32\CertFindCertificateInStore" 279 | , "ptr", hStore 280 | , "uint", dwCertEncodingType 281 | , "uint", dwFindFlags 282 | , "uint", dwFindType 283 | , FindParamType, FindParam 284 | , "ptr", ctx.p ; If non-NULL, this context is freed. 285 | , "ptr") 286 | { 287 | ; Each certificate context must be duplicated since the next 288 | ; call will free it. 289 | certs.Insert(ctx.Duplicate()) 290 | } 291 | ctx.p := 0 ; Above freed it already. 292 | return certs 293 | } 294 | 295 | AddCertificate(Certificate, dwAddDisposition) 296 | { 297 | if !DllCall("Crypt32\CertAddCertificateContextToStore" 298 | , "ptr", this.h 299 | , "ptr", Certificate.p 300 | , "uint", dwAddDisposition 301 | , "ptr*", pStoreContext) 302 | return 0 303 | global Cert 304 | return pStoreContext ? new Cert.Context(pStoreContext) : 0 305 | } 306 | 307 | __New(handle) 308 | { 309 | this.h := handle 310 | } 311 | 312 | __Delete() 313 | { 314 | if this.h && DllCall("Crypt32\CertCloseStore", "ptr", this.h, "uint", 0) 315 | this.h := 0 316 | } 317 | 318 | static Dispose := Cert.Store.__Delete ; Alias 319 | } 320 | 321 | 322 | ; 323 | ; Certificate Context 324 | ; 325 | class Context 326 | { 327 | __New(ptr) 328 | { 329 | this.p := ptr 330 | } 331 | 332 | __Delete() 333 | { 334 | if this.p && DllCall("Crypt32\CertFreeCertificateContext", "ptr", this.p) 335 | this.p := 0 336 | } 337 | 338 | ; CertGetNameString 339 | ; http://msdn.microsoft.com/en-us/library/aa376086 340 | GetNameString(dwType, dwFlags=0, pvTypePara=0) 341 | { 342 | if !this.p 343 | return 344 | cc := DllCall("Crypt32\CertGetNameString", "ptr", this.p, "uint", dwType, "uint", dwFlags, "ptr", pvTypePara, "ptr", 0, "uint", 0) 345 | if cc <= 1 ; i.e. empty string. 346 | return 347 | VarSetCapacity(name, cc*2) 348 | DllCall("Crypt32\CertGetNameString", "ptr", this.p, "uint", dwType, "uint", dwFlags, "ptr", pvTypePara, "str", name, "uint", cc) 349 | return name 350 | } 351 | 352 | ; CertDuplicateCertificateContext 353 | ; http://msdn.microsoft.com/en-us/library/aa376045 354 | Duplicate() 355 | { 356 | return this.p && (p := DllCall("Crypt32\CertDuplicateCertificateContext", "ptr", this.p)) 357 | ? new this.base(p) : p 358 | } 359 | 360 | static Dispose := Cert.Context.__Delete ; Alias 361 | } 362 | 363 | 364 | ; 365 | ; Error Detection 366 | ; 367 | __Get(name) 368 | { 369 | ListLines 370 | MsgBox 16,, Attempt to access invalid property Cert.%name%. 371 | Pause 372 | } 373 | } 374 | 375 | 376 | ; 377 | ; Internal 378 | ; 379 | 380 | Cert_GetStoreNames_Callback(pvSystemStore, dwFlags, pStoreInfo, pvReserved, pvArg) 381 | { 382 | Object(pvArg).Insert(StrGet(pvSystemStore, "utf-16")) 383 | return true 384 | } -------------------------------------------------------------------------------- /AHK/Lib/Crypt.ahk: -------------------------------------------------------------------------------- 1 | class Crypt 2 | { 3 | ; Provider Types 4 | static PROV_RSA_FULL := 1 5 | , PROV_RSA_SIG := 2 6 | , PROV_DSS := 3 7 | , PROV_FORTEZZA := 4 8 | , PROV_MS_EXCHANGE := 5 9 | , PROV_SSL := 6 10 | , PROV_STT_MER := 7 ; <= XP 11 | , PROV_STT_ACQ := 8 ; <= XP 12 | , PROV_STT_BRND := 9 ; <= XP 13 | , PROV_STT_ROOT := 10 ; <= XP 14 | , PROV_STT_ISS := 11 ; <= XP 15 | , PROV_RSA_SCHANNEL := 12 16 | , PROV_DSS_DH := 13 17 | , PROV_EC_ECDSA_SIG := 14 18 | , PROV_EC_ECNRA_SIG := 15 19 | , PROV_EC_ECDSA_FULL := 16 20 | , PROV_EC_ECNRA_FULL := 17 21 | , PROV_DH_SCHANNEL := 18 22 | , PROV_SPYRUS_LYNKS := 20 23 | , PROV_RNG := 21 24 | , PROV_INTEL_SEC := 22 25 | , PROV_REPLACE_OWF := 23 ; >= XP 26 | , PROV_RSA_AES := 24 ; >= XP 27 | 28 | ; CryptAcquireContext - dwFlags 29 | ; http://msdn.microsoft.com/en-us/library/aa379886 30 | static VERIFYCONTEXT := 0xF0000000 31 | , NEWKEYSET := 0x00000008 32 | , DELETEKEYSET := 0x00000010 33 | , MACHINE_KEYSET := 0x00000020 34 | , SILENT := 0x00000040 35 | , CRYPT_DEFAULT_CONTAINER_OPTIONAL := 0x00000080 36 | 37 | ; CryptGenKey - dwFlag 38 | ; http://msdn.microsoft.com/en-us/library/aa379941 39 | static EXPORTABLE := 0x00000001 40 | , USER_PROTECTED := 0x00000002 41 | , CREATE_SALT := 0x00000004 42 | , UPDATE_KEY := 0x00000008 43 | , NO_SALT := 0x00000010 44 | , PREGEN := 0x00000040 45 | , ARCHIVABLE := 0x00004000 46 | , FORCE_KEY_PROTECTION_HIGH := 0x00008000 47 | 48 | ; Key Types 49 | static AT_KEYEXCHANGE := 1 50 | , AT_SIGNATURE := 2 51 | 52 | ; 53 | ; METHODS 54 | ; 55 | 56 | AcquireContext(Container, Provider, dwProvType, dwFlags) 57 | { 58 | if DllCall("Advapi32\CryptAcquireContext" 59 | , "ptr*", hProv 60 | , "ptr", Container ? &Container : 0 61 | , "ptr", Provider ? &Provider : 0 62 | , "uint", dwProvType 63 | , "uint", dwFlags) 64 | { 65 | if (dwFlags & this.DELETEKEYSET) 66 | ; Success, but hProv is invalid in this case. 67 | return 1 68 | ; Wrap it up so it'll be released at some point. 69 | return new this.Context(hProv) 70 | } 71 | return 0 72 | } 73 | 74 | IsSigned(FilePath) 75 | { 76 | return DllCall("Crypt32\CryptQueryObject" 77 | , "uint", CERT_QUERY_OBJECT_FILE := 1 78 | , "wstr", FilePath 79 | , "uint", CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED := 1<<10 80 | , "uint", CERT_QUERY_FORMAT_FLAG_BINARY := 2 81 | , "uint", 0 82 | , "uint*", dwEncoding 83 | , "uint*", dwContentType 84 | , "uint*", dwFormatType 85 | , "ptr", 0 86 | , "ptr", 0 87 | , "ptr", 0) 88 | } 89 | 90 | ; 91 | ; Error Detection 92 | ; 93 | __Get(name) 94 | { 95 | ListLines 96 | MsgBox 16,, Attempt to access invalid property Crypt.%name%. 97 | Pause 98 | } 99 | 100 | ; 101 | ; CLASSES 102 | ; 103 | 104 | class _Handle 105 | { 106 | __New(handle) 107 | { 108 | this.h := handle 109 | } 110 | 111 | __Delete() 112 | { 113 | this.Dispose() 114 | } 115 | } 116 | 117 | class Context extends Crypt._Handle 118 | { 119 | GenerateKey(KeyType, KeyBitLength, dwFlags) 120 | { 121 | if DllCall("Advapi32\CryptGenKey" 122 | , "ptr", this.h 123 | , "uint", KeyType 124 | , "uint", (KeyBitLength << 16) | dwFlags 125 | , "ptr*", hKey) 126 | { 127 | global Crypt 128 | return new Crypt.Key(hKey) 129 | } 130 | return 0 131 | } 132 | 133 | CreateSelfSignCertificate(NameObject, StartTime, EndTime) 134 | { 135 | ctx := DllCall("Crypt32\CertCreateSelfSignCertificate" 136 | , "ptr", this.h 137 | , "ptr", IsObject(NameObject) ? NameObject.p : NameObject 138 | , "uint", 0, "ptr", 0, "ptr", 0 139 | , "ptr", IsObject(StartTime) ? StartTime.p : StartTime 140 | , "ptr", IsObject(EndTime) ? EndTime.p : EndTime 141 | , "ptr", 0, "ptr") 142 | global Cert 143 | return ctx ? new Cert.Context(ctx) : 0 144 | } 145 | 146 | Dispose() 147 | { 148 | if this.h && DllCall("Advapi32\CryptReleaseContext", "ptr", this.h, "uint", 0) 149 | this.h := 0 150 | } 151 | } 152 | 153 | class Key extends Crypt._Handle 154 | { 155 | Dispose() 156 | { 157 | if this.h && DllCall("Advapi32\CryptDestroyKey", "ptr", this.h) 158 | this.h := 0 159 | } 160 | } 161 | } -------------------------------------------------------------------------------- /AHK/Lib/SignFile.ahk: -------------------------------------------------------------------------------- 1 | SignFile(File, CertCtx, Name) 2 | { 3 | VarSetCapacity(wfile, 2 * StrPut(File, "utf-16")), StrPut(File, &wfile, "utf-16") 4 | VarSetCapacity(wname, 2 * StrPut(Name, "utf-16")), StrPut(Name, &wname, "utf-16") 5 | cert_ptr := IsObject(CertCtx) ? CertCtx.p : CertCtx 6 | 7 | VarSetCapacity(file_info, A_PtrSize*3, 0) ; SIGNER_FILE_INFO 8 | NumPut(3*A_PtrSize, file_info, 0) 9 | NumPut(&wfile, file_info, A_PtrSize) 10 | 11 | VarSetCapacity(dwIndex, 4, 0) 12 | 13 | VarSetCapacity(subject_info, A_PtrSize*4, 0) ; SIGNER_SUBJECT_INFO 14 | NumPut(A_PtrSize*4, subject_info, 0) 15 | NumPut(&dwIndex, subject_info, A_PtrSize) ; MSDN: "must be set to zero" in this case means "must be set to the address of a field containing zero". 16 | NumPut(SIGNER_SUBJECT_FILE:=1, subject_info, A_PtrSize*2) 17 | NumPut(&file_info, subject_info, A_PtrSize*3) 18 | 19 | VarSetCapacity(cert_store_info, A_PtrSize*4, 0) ; SIGNER_CERT_STORE_INFO 20 | NumPut(A_PtrSize*4, cert_store_info, 0) 21 | NumPut(cert_ptr, cert_store_info, A_PtrSize) 22 | NumPut(SIGNER_CERT_POLICY_CHAIN:=2, cert_store_info, A_PtrSize*3) 23 | 24 | VarSetCapacity(cert_info, 8+A_PtrSize*2, 0) ; SIGNER_CERT 25 | NumPut(8+A_PtrSize*2, cert_info, 0, "uint") 26 | NumPut(SIGNER_CERT_STORE:=2, cert_info, 4, "uint") 27 | NumPut(&cert_store_info, cert_info, 8) 28 | 29 | VarSetCapacity(authcode_attr, 8+A_PtrSize*3, 0) ; SIGNER_ATTR_AUTHCODE 30 | NumPut(8+A_PtrSize*3, authcode_attr, 0, "uint") 31 | NumPut(false, authcode_attr, 4, "int") ; fCommercial 32 | NumPut(true, authcode_attr, 8) ; fIndividual 33 | NumPut(&wname, authcode_attr, 8+A_PtrSize) 34 | 35 | VarSetCapacity(sig_info, 8+A_PtrSize*4, 0) ; SIGNER_SIGNATURE_INFO 36 | NumPut(8+A_PtrSize*4, sig_info, 0, "uint") 37 | NumPut(CALG_SHA1:=0x8004, sig_info, 4, "uint") 38 | NumPut(SIGNER_AUTHCODE_ATTR:=1, sig_info, 8) 39 | NumPut(&authcode_attr, sig_info, 8+A_PtrSize) 40 | 41 | hr := DllCall("MSSign32\SignerSign" 42 | , "ptr", &subject_info 43 | , "ptr", &cert_info 44 | , "ptr", &sig_info 45 | , "ptr", 0 ; pProviderInfo 46 | , "ptr", 0 ; pwszHttpTimeStamp 47 | , "ptr", 0 ; psRequest 48 | , "ptr", 0 ; pSipData 49 | , "uint") 50 | 51 | return 0 == (ErrorLevel := hr) 52 | } -------------------------------------------------------------------------------- /AHK/Lib/SystemTime.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | SystemTime - Wrapper for Win32 SYSTEMTIME Structure 3 | http://msdn.microsoft.com/en-us/library/ms724950 4 | 5 | Usage Examples: 6 | 7 | ; Create structure from string. 8 | st := SystemTime.FromString(A_Now) 9 | 10 | ; Shortcut: 11 | st := SystemTime.Now() 12 | 13 | ; Update values. 14 | st.FromString(A_Now) 15 | 16 | ; Retrieve components. 17 | year := st.Year 18 | month := st.Month 19 | weekday := st.DayOfWeek 20 | day := st.Day 21 | hour := st.Hour 22 | minute := st.Minute 23 | second := st.Second 24 | ms := st.Milliseconds 25 | 26 | ; Set or perform math on component. 27 | st.Year += 10 28 | 29 | ; Create structure to receive output from DllCall. 30 | st := new SystemTime 31 | DllCall("GetSystemTime", "ptr", st.p) 32 | MsgBox % st.ToString() 33 | 34 | ; Fill external structure. 35 | st := SystemTime.FromPointer(externalPointer) 36 | st.FromString(A_Now) 37 | 38 | ; Convert external structure to string. 39 | MsgBox % SystemTime.ToString(externalPointer) 40 | 41 | */ 42 | 43 | class SystemTime 44 | { 45 | FromString(str) 46 | { 47 | if this.p 48 | st := this 49 | else 50 | st := new this 51 | if !(p := st.p) 52 | return 0 53 | FormatTime wday, %str%, WDay 54 | wday -= 1 55 | FormatTime str, %str%, yyyy M '%wday%' d H m s '0' 56 | Loop Parse, str, %A_Space% 57 | NumPut(A_LoopField, p+(A_Index-1)*2, "ushort") 58 | return st 59 | } 60 | 61 | FromPointer(pointer) 62 | { 63 | return { p: pointer, base: this } ; Does not call __New. 64 | } 65 | 66 | ToString(st = 0) 67 | { 68 | if !(p := (st ? (IsObject(st) ? st.p : st) : this.p)) 69 | return "" 70 | VarSetCapacity(s, 28), s := SubStr("000" NumGet(p+0, "ushort"), -3) 71 | Loop 6 72 | if A_Index != 2 73 | s .= SubStr("0" NumGet(p+A_Index*2, "ushort"), -1) 74 | return s 75 | } 76 | 77 | Now() 78 | { 79 | return this.FromString(A_Now) 80 | } 81 | 82 | __New() 83 | { 84 | if !(this.SetCapacity("struct", 16)) 85 | || !(this.p := this.GetAddress("struct")) 86 | return 0 87 | NumPut(0, NumPut(0, this.p, "int64"), "int64") 88 | } 89 | 90 | __GetSet(name, value="") 91 | { 92 | static fields := {Year:0, Month:2, DayOfWeek:4, Day:6, Hour:8 93 | , Minute:10, Second:12, Milliseconds:14} 94 | if fields.HasKey(name) 95 | return value="" 96 | ? NumGet( this.p + fields[name], "ushort") 97 | : NumPut(value, this.p + fields[name], "ushort") 98 | } 99 | static __Get := SystemTime.__GetSet 100 | static __Set := SystemTime.__GetSet 101 | } -------------------------------------------------------------------------------- /AHK/Setup.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | @author: XJK 3 | @github: https://github.com/XUJINKAI/OneQuick 4 | */ 5 | #NoTrayIcon 6 | #SingleInstance force 7 | #Include, Compile.ahk 8 | SetWorkingDir, %A_ScriptDir% 9 | 10 | para1 = %1% 11 | para2 = %2% 12 | silent := para1=="/S" 13 | callback := para2 14 | 15 | if not A_IsCompiled 16 | { 17 | compile_ahk(A_ScriptName) 18 | ExitApp 19 | } 20 | 21 | if(!silent) 22 | { 23 | msg = Install Autohotkey? `n`n安装Autohotkey吗? 24 | msgbox, 0x24,, % msg 25 | IfMsgBox, NO 26 | { 27 | ExitApp 28 | } 29 | } 30 | 31 | if(!A_IsAdmin) 32 | { 33 | Run *RunAs %A_ScriptFullPath% /S "%para2%",, UseErrorLevel 34 | ExitApp 35 | } 36 | 37 | ; run installer silent 38 | RunWait, AutoHotkey_Install.exe /S,, UseErrorLevel 39 | 40 | ; enable UIAccess 41 | RunWait, Autohotkey.exe EnableUIAccess2AHK.ahk /S,, UseErrorLevel 42 | 43 | if(callback!="") 44 | { 45 | Run, %callback%,, UseErrorLevel 46 | } 47 | else 48 | { 49 | msgbox, 0x20,, Autohotkey Installed. 50 | } 51 | ExitApp -------------------------------------------------------------------------------- /OneQuick Launcher.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | @author: XJK 3 | @github: https://github.com/XUJINKAI/OneQuick 4 | */ 5 | 6 | #NoTrayIcon 7 | #SingleInstance force 8 | #Include, AHK\compile.ahk 9 | SetWorkingDir, %A_ScriptDir% 10 | 11 | ProgramName = "OneQuick" 12 | program_icon := "icon/1.ico" 13 | OneQuickAHKPath := "script/OneQuick.ahk" 14 | AHK_installer := "AHK\setup.exe" 15 | 16 | if not A_IsCompiled 17 | { 18 | compile_ahk(A_ScriptName, program_icon) 19 | ExitApp 20 | } 21 | 22 | Run, AutoHotkey.exe %OneQuickAHKPath%, , UseErrorLevel 23 | if ErrorLevel = Error 24 | { 25 | Gosub, SUB_AHK_INSTALL 26 | } 27 | ExitApp 28 | 29 | SUB_AHK_INSTALL: 30 | msg = Install Autohotkey?`n`n安装Autohotkey吗? 31 | msgbox, 0x24,, % msg 32 | IfMsgBox, NO 33 | { 34 | ExitApp 35 | } 36 | 37 | RunWait, %AHK_installer% /S "%A_ScriptFullPath%",, UseErrorLevel 38 | if ErrorLevel = ERROR 39 | { 40 | MsgBox, 0x30, %ProgramName%, Run %AHK_installer% ERROR. 41 | ExitApp 42 | } 43 | 44 | MsgBox, 0x0, , autohotkey installing... 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 新版已上架微软应用商店,此版停止更新支持。 2 | ======================== 3 | 4 | 官网:[http://onequick.org/](http://onequick.org/?f=gh_ahk) 5 | ======================== 6 | 7 | OneQuick 是一款基于autohotkey的windows快捷工具。 8 | 独创的屏幕边缘操作、文本快速搜索功能;还有剪贴板历史纪录、窗口操作菜单等一系列实用功能,操作windows也能如此爽快。 9 | OneQuick也为扩展代码留下了足够的空间,你可以基于OneQuick提供的大量函数开发自己的ahk脚本。 10 | 11 | OneQuick is an Autohotkey script, it is both a convenient tool and an ahk library. 12 | It provides clipboard manager, screen border operation, window operation, quick menu, etc. 13 | It's also a useful library to write your own ahk code. 14 | 15 | 例:快速调整音量 16 | ![screenLT](http://i.imgur.com/mKVXXmU.gif) 17 | 18 | 19 | 安装 20 | ------------------------ 21 | 到下载最新的压缩包,解压执行**OneQuick Launcher.exe** 即可。 22 | _OneQuick基于[AHK][AHK],如果没有安装的话会先安装AHK。_ 23 | 24 | 25 | 帮助 & 文档 26 | ------------------------ 27 | 关于如何配置功能与开发,请[查看这里][DOCUMENT] 28 | 29 | 30 | 默认功能 31 | ------------------------ 32 | - **剪贴板增强 · clipboard** 33 | ctrl + shift + x:打开剪贴板记录 34 | ctrl + shift + c:复制并打开操作列表 35 | ctrl + shift + v:直接打开操作列表 36 | 37 | 在操作列表中: 38 | TAB: 粘贴 39 | 空格: 执行当前内容 (可以是网址、命令行、甚至b站av号) 40 | 字母按键: 使用搜索引擎搜索当前内容 (如b为百度,g为google,m为豆瓣电影等) 41 | 数字按键: 切换浏览器 (修改OneQuick内部默认的浏览器) 42 | 你也可以将当前的内容加入到收藏夹或删除 43 | 44 | - **屏幕边缘操作 · screen border** 45 | 46 | **左上角 · LT** 47 | 滚轮/单击滚轮:音量大小/静音 48 | shift + 滚轮:屏幕亮度 49 | 右键:窗口操作菜单 50 | 51 | **右上角 · RT** 52 | 滚轮/单击滚轮:歌曲上一首/下一首/播放或暂停 53 | 右键:用户自定义菜单([如何扩展菜单][ext_rt_menu]) 54 | 55 | **左边框 & 右边框 · L-R** 56 | 滚轮:翻页 57 | shift + 滚轮:翻页x5 58 | ctrl + shift + 滚轮:翻到第一页/最后一页 59 | 60 | **上边框 · T** 61 | 滚轮:标签页切换 62 | 63 | **下边框 · B** 64 | 滚轮/单击滚轮:(win10) 虚拟桌面切换/查看(win+tab键) 65 | 66 | - **应用增强 · app enhance** 67 | ctrl+w 关闭记事本 68 | chrome 标签滚轮切换 69 | 使用sublime时,按win+E 打开当前正在编辑的文件所在的目录 70 | 71 | - **快捷键 · hotkey** 72 | **win + Z:显示功能菜单(GreatMenu)** 73 | **ctrl + alt + R:打开Command Run窗口** ([可执行的命令说明][run_function]) 74 | win + 鼠标右键:弹出当前窗口的操作菜单 75 | shift + 滚轮:翻页 76 | win + T:当前窗口最前端 77 | win + N:打开系统记事本 78 | win + shift + L:立刻锁定计算机并关闭屏幕 79 | ctrl + shift + alt + R:重新启动OneQuick 80 | 81 | - **其他** 82 | 左键单击OneQuick托盘图标可以暂停程序运行; 83 | 右键单击OneQuick托盘图标可打开OneQuick菜单,设置自启动,打开脚本目录,或AHK帮助文件等; 84 | 85 | 86 | Q&A 87 | ------------------------ 88 | 89 | - #### OneQuick的由来? 90 | OneQuick开始于2014年初,最初只是自用,经历过几次大的重写,断断续续,到2015年左右成型。用到现在又快一年了,在这一年中,我发现我已经离不开OneQuick了,当临时使用别人的电脑时,会因为没有相关的快捷设置而无所适从。将OneQuick发布出来,也是作为自己研究生生涯的纪念。 91 | 92 | - #### OneQuick对某些程序失效? 93 | 运行/AHK/EnableUIAccess2AHK.ahk 即可。 94 | (需要Autohotkey安装在系统目录中,此方法针对UWP或管理员权限程序。) 95 | 96 | - #### 修改 OneQuick 默认的文本编辑器? 97 | 参考[这里][ext_default_editor] 98 | 99 | - #### 让OneQuick支持更多ahk功能,如快速输入字符串? 100 | 参考[这里][ext_ahk_code] 101 | 102 | - #### 执行b站av号是怎么回事? 103 | OneQuick可以“执行”【"av"+数字】格式的字串。 104 | 比如,按ctrl + shift + c 复制 `av314` 并弹出菜单后,再按空格即可打开相应视频。 105 | 扩展类似的功能可以参考[这里][run_function] 106 | 107 | - #### 剪贴板只能保存文本记录? 108 | 是的,OneQuick的剪贴板记录暂不支持图片等内容。不过,只要不利用OneQuick的剪贴板记录切换内容,系统剪贴板就不会受到影响。 109 | 110 | - #### 卸载Autohotkey提示无权限? 111 | 可以运行AHK/AutoHotkey_Install.exe选择uninstall卸载。 112 | 113 | 联系 114 | ------------------------ 115 | 作者:http://xujinkai.net/ 116 | 117 | 版权 · License 118 | ------------------------ 119 | 修改、分享请注明作者信息。 120 | > XJK: https://github.com/XUJINKAI 121 | 122 | 以GPL协议发布。 123 | 124 | [AHK]: https://autohotkey.com/ 125 | [DOCUMENT]: https://github.com/XUJINKAI/OneQuick/wiki 126 | [ext_rt_menu]: https://github.com/XUJINKAI/OneQuick/wiki/OneQuick.Ext.ahk#扩展屏幕右上角右键菜单 127 | [ext_default_editor]: https://github.com/XUJINKAI/OneQuick/wiki/OneQuick.Ext.ahk#设置默认编辑器 128 | [ext_ahk_code]: https://github.com/XUJINKAI/OneQuick/wiki/OneQuick.Ext.ahk#定义额外的快捷键 129 | [run_function]: https://github.com/XUJINKAI/OneQuick/wiki/run_function 130 | 131 | ------------------------ 132 | ##### FROM OTHER PROJECT 133 | JSON: https://github.com/cocobelgica/AutoHotkey-JSON 134 | YAML:https://github.com/HotKeyIt/Yaml 135 | ICON: http://www.iconarchive.com/show/flatastic-1-icons-by-custom-icon-design.html, http://www.iconarchive.com/show/flatastic-2-icons-by-custom-icon-design.html 136 | -------------------------------------------------------------------------------- /icon/1.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XUJINKAI/OneQuick.AHK-legacy/1d369893f3c38e5589ceeba6fda400659020b099/icon/1.ico -------------------------------------------------------------------------------- /icon/2.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XUJINKAI/OneQuick.AHK-legacy/1d369893f3c38e5589ceeba6fda400659020b099/icon/2.ico -------------------------------------------------------------------------------- /icon/3.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XUJINKAI/OneQuick.AHK-legacy/1d369893f3c38e5589ceeba6fda400659020b099/icon/3.ico -------------------------------------------------------------------------------- /icon/4.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XUJINKAI/OneQuick.AHK-legacy/1d369893f3c38e5589ceeba6fda400659020b099/icon/4.ico -------------------------------------------------------------------------------- /lang/cn.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XUJINKAI/OneQuick.AHK-legacy/1d369893f3c38e5589ceeba6fda400659020b099/lang/cn.ini -------------------------------------------------------------------------------- /lang/en.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XUJINKAI/OneQuick.AHK-legacy/1d369893f3c38e5589ceeba6fda400659020b099/lang/en.ini -------------------------------------------------------------------------------- /script/JSON.ahk: -------------------------------------------------------------------------------- 1 | /* Class: JSON 2 | * JSON lib for AutoHotkey 3 | * License: 4 | * WTFPL [http://wtfpl.net/] 5 | * Requirements: 6 | * AutoHotkey v1.1.17+ 7 | * Others: 8 | * Github URL: https://github.com/cocobelgica/AutoHotkey-JSON 9 | * Email: cocobelgica@gmail.com 10 | * Last Update: 02/15/2015 (MM/DD/YYYY) 11 | */ 12 | class JSON 13 | { 14 | /* Method: parse 15 | * Deserialize a string containing a JSON document to an AHK object. 16 | * Syntax: 17 | * json_obj := JSON.parse( ByRef src [ , jsonize := false ] ) 18 | * Parameter(s): 19 | * src [in, ByRef] - String containing a JSON document 20 | * jsonize [in] - If true, objects {} and arrays [] are wrapped as 21 | * JSON.object and JSON.array instances respectively. 22 | */ 23 | parse(ByRef src, jsonize:=false) 24 | { 25 | args := jsonize ? [ JSON.object, JSON.array ] : [] 26 | key := "", is_key := false 27 | stack := [ tree := [] ] 28 | is_arr := { (tree): 1 } 29 | next := """{[01234567890-tfn" 30 | pos := 0 31 | while ( (ch := SubStr(src, ++pos, 1)) != "" ) 32 | { 33 | if InStr(" `t`n`r", ch) 34 | continue 35 | if !InStr(next, ch) 36 | { 37 | ln := ObjMaxIndex(StrSplit(SubStr(src, 1, pos), "`n")) 38 | col := pos - InStr(src, "`n",, -(StrLen(src)-pos+1)) 39 | 40 | msg := Format("{}: line {} col {} (char {})" 41 | , (next == "") ? ["Extra data", ch := SubStr(src, pos)][1] 42 | : (next == "'") ? "Unterminated string starting at" 43 | : (next == "\") ? "Invalid \escape" 44 | : (next == ":") ? "Expecting ':' delimiter" 45 | : (next == """") ? "Expecting object key enclosed in double quotes" 46 | : (next == """}") ? "Expecting object key enclosed in double quotes or object closing '}'" 47 | : (next == ",}") ? "Expecting ',' delimiter or object closing '}'" 48 | : (next == ",]") ? "Expecting ',' delimiter or array closing ']'" 49 | : [ "Expecting JSON value(string, number, [true, false, null], object or array)" 50 | , ch := SubStr(src, pos, (SubStr(src, pos)~="[\]\},\s]|$")-1) ][1] 51 | , ln, col, pos) 52 | 53 | throw Exception(msg, -1, ch) 54 | } 55 | 56 | is_array := is_arr[obj := stack[1]] 57 | 58 | if i := InStr("{[", ch) 59 | { 60 | val := (proto := args[i]) ? new proto : {} 61 | is_array? ObjInsert(obj, val) : obj[key] := val 62 | ObjInsert(stack, 1, val) 63 | 64 | is_arr[val] := !(is_key := ch == "{") 65 | next := is_key ? """}" : """{[]0123456789-tfn" 66 | } 67 | 68 | else if InStr("}]", ch) 69 | { 70 | ObjRemove(stack, 1) 71 | next := stack[1]==tree ? "" : is_arr[stack[1]] ? ",]" : ",}" 72 | } 73 | 74 | else if InStr(",:", ch) 75 | { 76 | is_key := (!is_array && ch == ",") 77 | next := is_key ? """" : """{[0123456789-tfn" 78 | } 79 | 80 | else 81 | { 82 | if (ch == """") 83 | { 84 | i := pos 85 | while (i := InStr(src, """",, i+1)) 86 | { 87 | val := SubStr(src, pos+1, i-pos-1) 88 | StringReplace, val, val, \\, \u005C, A 89 | if (SubStr(val, 0) != "\") 90 | break 91 | } 92 | if !i ? (pos--, next := "'") : 0 93 | continue 94 | 95 | pos := i 96 | 97 | StringReplace, val, val, \/, /, A 98 | StringReplace, val, val, \", ", A 99 | StringReplace, val, val, \b, `b, A 100 | StringReplace, val, val, \f, `f, A 101 | StringReplace, val, val, \n, `n, A 102 | StringReplace, val, val, \r, `r, A 103 | StringReplace, val, val, \t, `t, A 104 | 105 | i := 0 106 | while (i := InStr(val, "\",, i+1)) 107 | { 108 | if (SubStr(val, i+1, 1) != "u") ? (pos -= StrLen(SubStr(val, i)), next := "\") : 0 109 | continue 2 110 | 111 | ; \uXXXX - JSON unicode escape sequence 112 | xxxx := Abs("0x" . SubStr(val, i+2, 4)) 113 | if (A_IsUnicode || xxxx < 0x100) 114 | val := SubStr(val, 1, i-1) . Chr(xxxx) . SubStr(val, i+6) 115 | } 116 | 117 | if is_key 118 | { 119 | key := val, next := ":" 120 | continue 121 | } 122 | } 123 | 124 | else 125 | { 126 | val := SubStr(src, pos, i := RegExMatch(src, "[\]\},\s]|$",, pos)-pos) 127 | 128 | static null := "" ; for #Warn 129 | if InStr(",true,false,null,", "," . val . ",", true) ; if var in 130 | val := %val% 131 | else if (Abs(val) == "") ? (pos--, next := "#") : 0 132 | continue 133 | 134 | val := val + 0, pos += i-1 135 | } 136 | 137 | is_array? ObjInsert(obj, val) : obj[key] := val 138 | next := obj==tree ? "" : is_array ? ",]" : ",}" 139 | } 140 | } 141 | 142 | return tree[1] 143 | } 144 | /* Method: stringify 145 | * Serialize an object to a JSON formatted string. 146 | * Syntax: 147 | * json_str := JSON.stringify( obj [ , indent := "" ] ) 148 | * Parameter(s): 149 | * obj [in] - The object to stringify. 150 | * indent [in] - Specify string(s) to use as indentation per level. 151 | */ 152 | stringify(obj:="", indent:="", lvl:=1) 153 | { 154 | if IsObject(obj) 155 | { 156 | if (ObjGetCapacity(obj) == "") ; COM,Func,RegExMatch,File,Property object 157 | throw Exception("Object type not supported.", -1, Format("", &obj)) 158 | 159 | is_array := 0 160 | for k in obj 161 | is_array := (k == A_Index) 162 | until !is_array 163 | 164 | if indent is integer 165 | { 166 | if (indent < 0) 167 | throw Exception("Indent parameter must be a postive integer.", -1, indent) 168 | spaces := indent, indent := "" 169 | Loop % spaces 170 | indent .= " " 171 | } 172 | indt := "" 173 | Loop, % indent ? lvl : 0 174 | indt .= indent 175 | 176 | lvl += 1, out := "" ; make #Warn happy 177 | for k, v in obj 178 | { 179 | if IsObject(k) || (k == "") 180 | throw Exception("Invalid object key.", -1, k ? Format("", &obj) : "") 181 | 182 | if !is_array 183 | out .= ( ObjGetCapacity([k], 1) ? JSON.stringify(k) : """" . k . """" ) ; key 184 | . ( indent ? ": " : ":" ) ; token + padding 185 | out .= JSON.stringify(v, indent, lvl) ; value 186 | . ( indent ? ",`n" . indt : "," ) ; token + indent 187 | } 188 | 189 | if (out != "") 190 | { 191 | out := Trim(out, ",`n" indent) 192 | if (indent != "") 193 | out := Format("`n{}{}`n{}", indt, out, SubStr(indt, StrLen(indent)+1)) 194 | } 195 | 196 | return is_array ? "[" . out . "]" : "{" . out . "}" 197 | } 198 | 199 | ; Number 200 | if (ObjGetCapacity([obj], 1) == "") ; returns an integer if 'obj' is string 201 | return obj 202 | 203 | ; String (null -> not supported by AHK) 204 | if (obj != "") 205 | { 206 | StringReplace, obj, obj, \, \\, A 207 | StringReplace, obj, obj, /, \/, A 208 | StringReplace, obj, obj, ", \", A 209 | StringReplace, obj, obj, `b, \b, A 210 | StringReplace, obj, obj, `f, \f, A 211 | StringReplace, obj, obj, `n, \n, A 212 | StringReplace, obj, obj, `r, \r, A 213 | StringReplace, obj, obj, `t, \t, A 214 | 215 | while RegExMatch(obj, "[^\x20-\x7e]", m) 216 | StringReplace, obj, obj, %m%, % Format("\u{:04X}", Asc(m)), A 217 | } 218 | 219 | return """" . obj . """" 220 | } 221 | 222 | class object 223 | { 224 | 225 | __New(args*) 226 | { 227 | ObjInsert(this, "_", []) 228 | if ((count := NumGet(&args+4*A_PtrSize)) & 1) 229 | throw "Invalid number of parameters" 230 | Loop % count//2 231 | this[args[A_Index*2-1]] := args[A_Index*2] 232 | } 233 | 234 | __Set(key, val, args*) 235 | { 236 | ObjInsert(this._, key) 237 | } 238 | 239 | Insert(key, val) 240 | { 241 | return this[key] := val 242 | } 243 | /* Buggy - remaining integer keys are not adjusted 244 | Remove(args*) { 245 | ret := ObjRemove(this, args*), i := -1 246 | for index, key in ObjClone(this._) { 247 | if ObjHasKey(this, key) 248 | continue 249 | ObjRemove(this._, index-(i+=1)) 250 | } 251 | return ret 252 | } 253 | */ 254 | Count() 255 | { 256 | return NumGet(&(this._) + 4*A_PtrSize) ; Round(this._.MaxIndex()) 257 | } 258 | 259 | stringify(indent:="") 260 | { 261 | return JSON.stringify(this, indent) 262 | } 263 | 264 | _NewEnum() 265 | { 266 | static proto := { "Next": JSON.object.Next } 267 | return { base: proto, enum: this._._NewEnum(), obj: this } 268 | } 269 | 270 | Next(ByRef key, ByRef val:="") 271 | { 272 | if (ret := this.enum.Next(i, key)) 273 | val := this.obj[key] 274 | return ret 275 | } 276 | } 277 | 278 | class array 279 | { 280 | 281 | __New(args*) 282 | { 283 | args.base := this.base 284 | return args 285 | } 286 | 287 | stringify(indent:="") 288 | { 289 | return JSON.stringify(this, indent) 290 | } 291 | } 292 | } -------------------------------------------------------------------------------- /script/OneQuick.Core.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | @author: XJK 3 | @github: https://github.com/XUJINKAI/OneQuick 4 | 请保留作者信息。please retain author information. 5 | 6 | 此文件是OneQuick的核心,定义了几个主要功能的class, 7 | 此文件的内容不会直接执行,需要OneQuick.ahk引用并依需要的功能启动, 8 | 所以一般无需修改此文件,也欢迎上github提交完善此项目。 9 | 10 | This is main class file of OneQuick, you need NOT modify it generally. 11 | you can pull requests in github for this project. 12 | */ 13 | 14 | ; parameters passed in 15 | argv1 = %1% 16 | ; Tray.Tip 17 | if(argv1="-traytip") { 18 | argv2 = %2% 19 | argv3 = %3% 20 | argv4 = %4% 21 | TrayTip, % argv2, % argv3,, % argv4 22 | } 23 | if(A_ScriptName=="OneQuick.Core.ahk") { 24 | ExitApp 25 | } 26 | ; with this label, you can include this file on top of the file 27 | Goto, SUB_ONEQUICK_FILE_END_LABEL 28 | #Persistent 29 | #MaxHotkeysPerInterval 200 30 | #MaxThreads, 255 31 | #MaxThreadsPerHotkey, 20 32 | #Include %A_ScriptDir% 33 | ; JSON.ahk From 34 | ; https://github.com/cocobelgica/AutoHotkey-JSON 35 | #Include, JSON.ahk 36 | ; https://github.com/HotKeyIt/Yaml 37 | ; https://autohotkey.com/board/topic/65582-ahk-lv2-yaml-yaml-parser-json/ 38 | #Include, Yaml.ahk 39 | ; 40 | #Include, ../ 41 | #Include, *i OneQuick.Ext.ahk 42 | #Include, %A_ScriptDir% 43 | ; ///////////////////////////////////// 44 | /* 45 | OneQuick 46 | */ 47 | class OneQuick 48 | { 49 | ; dir 50 | static _MAIN_WORKDIR := "" 51 | static _JSON_DIR := "data/" 52 | static _ICON_DIR := "icon/" 53 | static _LANG_DIR := "lang/" 54 | static _SCRIPT_DIR := "script/" 55 | static _Update_bkp_DIR := "_bkp/" 56 | static _Update_dl_DIR := "_bkp/dl/" 57 | static _Update_bkp_folder_prefix := "_auto_" 58 | ; file 59 | static Launcher_Name := A_WorkingDir "\OneQuick Launcher.exe" 60 | static Ext_ahk_file := "OneQuick.Ext.ahk" 61 | static version_yaml_file := OneQuick._SCRIPT_DIR "version.yaml" 62 | static feature_yaml_file := "OneQuick.feature.yaml" 63 | static feature_yaml_default_file := OneQuick._SCRIPT_DIR "OneQuick.feature.default.yaml" 64 | static config_file := "config.ini" 65 | static user_data_file := OneQuick._JSON_DIR "OneQuick.Data." A_ComputerName ".json" 66 | static icon_default := OneQuick._ICON_DIR "1.ico" 67 | static icon_suspend := OneQuick._ICON_DIR "2.ico" 68 | static icon_pause := OneQuick._ICON_DIR "4.ico" 69 | static icon_suspend_pause := OneQuick._ICON_DIR "3.ico" 70 | ; remote file path 71 | static remote_branch := "master" 72 | static remote_raw := "http://raw.githubusercontent.com/XUJINKAI/OneQuick/" OneQuick.remote_branch "/" 73 | static remote_releases_dir := "https://github.com/XUJINKAI/OneQuick/releases/download/" 74 | static remote_update_dl_dir := OneQuick.remote_releases_dir "beta0/" 75 | ; github api has limit 76 | ; static remote_contents := "https://api.github.com/repos/XUJINKAI/OneQuick/contents/" 77 | ; update 78 | static check_update_first_after := 1 79 | static check_update_period := 1000*3600*24 80 | static Bkp_limit := 5 81 | static update_list_path := OneQuick._SCRIPT_DIR "update_list.json" 82 | ; online 83 | static Project_Home_Page := "https://github.com/XUJINKAI/OneQuick" 84 | static Project_Issue_page := "https://github.com/XUJINKAI/OneQuick/issues" 85 | static remote_download_html := "https://github.com/XUJINKAI/OneQuick/releases" 86 | static remote_help := "https://github.com/XUJINKAI/OneQuick/wiki" 87 | ; 88 | ; setting object (read only, for feature configuration) 89 | static FeatureObj = 90 | ; version object (read only, for check update) 91 | static versionObj = 92 | ; running user data (e.g. clipboard history), read after run & write before exit 93 | static UserData := {} 94 | ; callback 95 | static OnExitCmd := [] 96 | static OnClipboardChangeCmd := [] 97 | static OnPauseCmd := [] 98 | static OnSuspendCmd := [] 99 | ; static var 100 | static ProgramName := "OneQuick" 101 | static Default_lang := "cn" 102 | static Editor = notepad 103 | static Browser := "default" 104 | 105 | Ini(asLib=false) 106 | { 107 | SetBatchLines, -1 ; maximize script speed! 108 | SetWinDelay, -1 109 | CoordMode, Mouse, Screen 110 | CoordMode, ToolTip, Screen 111 | CoordMode, Menu, Screen 112 | ; %systmeroot% can't give to this.Editor directly 113 | if(this.Editor = "" or this.Editor = "notepad") 114 | { 115 | defNotepad = %SystemRoot%\notepad.exe 116 | this.Editor := defNotepad 117 | } 118 | if(asLib) { 119 | Return 120 | } 121 | ; set _DEBUG_ value 122 | ; add show=1 to config.ini [debug] to show debug switch in menu 123 | OneQuick._DEBUG_ := OneQuick.debugConfig("debug", 0) 124 | 125 | ; register onexit sub 126 | OnExit, Sub_OnExit 127 | 128 | ; setting 129 | this.LoadFeatureYaml() 130 | ; load version yaml file 131 | this.versionObj := Yaml(this.version_yaml_file) 132 | ; program running cache/variable 133 | this.LoadUserData() 134 | 135 | ; initialize module 136 | xClipboard.Ini() 137 | WinMenu.Ini() 138 | 139 | ; initialize 140 | this.Update_Tray_Menu() 141 | this.SetAutorun("config") 142 | this.Show_StartInfo() 143 | ; guide 144 | this.Check_First_Time_Run() 145 | ; update 146 | SetTimer, Sub_Auto_Check_update, % -OneQuick.check_update_first_after 147 | ; ext.ahk 148 | this.Run_ext_user_ini() 149 | } 150 | ; when start 151 | Show_StartInfo() 152 | { 153 | msg := lang("traytip_runing") 154 | auto_update := OneQuick.GetConfig("auto_update") 155 | from_ver := OneQuick.GetConfig("update_from_version", "") 156 | msgbox_from_version := OneQuick.GetConfig("msgbox_from_version") 157 | if(OneQuick._DEBUG_) { 158 | msg .= "`n【DEBUG mode】" 159 | } 160 | if(msgbox_from_version!=from_ver) { 161 | update_tip := lang("Updated to version v") OneQuick.versionObj["version"] 162 | msg .= "`n" update_tip 163 | } 164 | bigver := this.GetBiggerRemVersion() 165 | if(bigver!="") { 166 | msg .= "`n" lang("new_version_traytip") " v" bigver 167 | } 168 | ; 先弹tip再弹msgbox 169 | Tray.Tip(msg) 170 | ; 从旧版本升级上来的提示 171 | ; 仅在第一次重启后显示 172 | if(msgbox_from_version!=from_ver) { 173 | if(!auto_update) { 174 | update_msg := OneQuick._new_version_info({"version": from_ver }, OneQuick.versionObj) 175 | m(update_tip "`n" update_msg) 176 | } 177 | OneQuick.SetConfig("msgbox_from_version", from_ver) 178 | } 179 | if(!auto_update) { 180 | if(bigver!="") { 181 | msgbox_newer_version := OneQuick.GetConfig("msgbox_newer_version") 182 | if(msgbox_newer_version!=bigver) { 183 | ; OneQuick.Check_update 弹窗, msgbox_newer_version 限制仅一次 184 | OneQuick.Check_update(true, false) 185 | OneQuick.SetConfig("msgbox_newer_version", bigver) 186 | } 187 | } 188 | } 189 | } 190 | ; user guide 191 | Check_First_Time_Run() 192 | { 193 | skip_guide := OneQuick.GetConfig("skip_guide") 194 | if(OneQuick._DEBUG_) { 195 | ; skip_guide := 0 196 | } 197 | if(!skip_guide) { 198 | run("autohotkey.exe " OneQuick._script_DIR "user_guide.ahk") 199 | OneQuick.SetConfig("skip_guide", 1) 200 | } 201 | } 202 | 203 | ; ext.ahk 204 | Run_ext_user_ini() 205 | { 206 | user_str := "User_" A_ComputerName 207 | StringReplace, user_str, user_str, - , _, All 208 | user_str := RegExReplace(user_str, "[^a-zA-Z0-9_]") 209 | if IsFunc(user_str ".Ini") 210 | { 211 | %user_str%.Ini() 212 | } 213 | Else 214 | { 215 | str := "`nclass " user_str "`n{`n`tIni()`n`t{`n`n`t}`n}`n`n" 216 | FileAppend, % str, % this.Ext_ahk_file 217 | } 218 | } 219 | 220 | ; Get 221 | Get_Remote_File(path) 222 | { 223 | StringReplace, path, % path, \, /, All 224 | url := OneQuick.remote_raw path 225 | content := http.get(url) 226 | return % content 227 | } 228 | ; 229 | Get_Remote_versionObj() 230 | { 231 | remoteVerTxt := OneQuick.Get_Remote_File(OneQuick.version_yaml_file) 232 | if(remoteVerTxt="") { 233 | return "" 234 | } 235 | remoteVerObj := Yaml(remoteVerTxt, 0) 236 | return remoteVerObj 237 | } 238 | 239 | ; check update 240 | ; show_msg=1, 弹窗升级; =0 静默升级; 241 | ; show_msg=1时, error_msg控制无需更新时的提示 242 | ; 默认由右键菜单调用,所以为true, true 243 | Check_update(show_msg=True, error_msg=True) 244 | { 245 | thisVerObj := OneQuick.versionObj 246 | remoteVerObj := OneQuick.Get_Remote_versionObj() 247 | this_version := thisVerObj["version"] 248 | remote_version := remoteVerObj["version"] 249 | if(remoteVerObj="") 250 | { 251 | if(show_msg&&error_msg) { 252 | msg := lang("update_http_error") 253 | m(msg) 254 | } 255 | Return 256 | } 257 | OneQuick.SetConfig("remote_version", remote_version) 258 | OneQuick.Update_Tray_Menu() 259 | ver_compare := OneQuick._version_compare(this_version, remote_version) 260 | if(ver_compare>=0) { 261 | if(show_msg&&error_msg) { 262 | msg := lang("update_no_newer_ver") 263 | if(ver_compare>0) { 264 | msg .= "`n你的版本号超过了作者...(ง •̀_•́)ง " 265 | } 266 | msg .= "`nv" this_version " -> v" remote_version 267 | m(msg) 268 | } 269 | Return 270 | } 271 | if(show_msg) { 272 | update_msg := lang("update_msg") 273 | if(OneQuick._DEBUG_) { 274 | update_msg := "【DEBUG Mode】`n" update_msg 275 | } 276 | new_version_info := OneQuick._new_version_info(thisVerObj, remoteVerObj) 277 | nv_msg := lang("new_version") 278 | MsgBox, 0x1024, % OneQuick.ProgramName " " nv_msg, % update_msg "`n" new_version_info 279 | IfMsgBox, NO 280 | { 281 | Return 282 | } 283 | } 284 | else { 285 | if(OneQuick.GetConfig("auto_update")=0) { 286 | Return 287 | } 288 | } 289 | ; set var 290 | FormatTime, timestr,, yyyyMMddHHmmss 291 | backup_dir := OneQuick._Update_bkp_DIR OneQuick._Update_bkp_folder_prefix timestr "_v" this_version "/" 292 | dl_dir := OneQuick._Update_dl_DIR 293 | update_background_tip := lang("update_background_tip", "Update in background") "..." 294 | ; 两种升级策略 295 | ; 1. 获取升级列表,并按列表按需下载所需文件(raw repo contents) 296 | ; 2. 下载压缩包 297 | bool_auto_update := OneQuick._version_compare(this_version, remoteVerObj["auto-update-version"]) >= 0 298 | if( ! bool_auto_update) { 299 | ; 由于smartscreen筛选,exe无法下载 300 | ; 故下载zip文件后告知用户手动解压 301 | ; download zip file 302 | if(show_msg) { 303 | d("method 2") 304 | Tray.Tip(update_background_tip) 305 | zip_name := "OneQuick.v" remote_version ".zip" 306 | remote_zip_file := OneQuick.remote_releases_dir "v" remote_version "/" zip_name 307 | ErrorLevel := File.Download(remote_zip_file, zip_name) 308 | d("dl zip, error: " ErrorLevel) 309 | if(ErrorLevel) { 310 | if(show_msg&&error_msg) { 311 | msg := lang("dl_zip_error") 312 | m(msg) 313 | run(OneQuick.remote_download_html) 314 | } 315 | Return 316 | } 317 | msg := lang("dl_zip_success") 318 | m(msg) 319 | run("explorer /select, " zip_name) 320 | } 321 | Return 322 | } 323 | d("method 1") 324 | ; tray tip 325 | Tray.Tip(update_background_tip) 326 | ; start operate files 327 | ; future: compare file & 增量升级 328 | OneQuick.Generate_update_list() 329 | ; clear bkp 330 | OneQuick._clear_bkp_folders() 331 | ; delete dl folder 332 | FileRemoveDir, % dl_dir, 1 333 | d("del dl") 334 | ; get update list in repo 335 | remote_json_str := OneQuick.Get_Remote_File(OneQuick.update_list_path) 336 | obj := JSON.parse(remote_json_str) 337 | ; download 338 | OneQuick._update_copy_file(obj, OneQuick.remote_raw, dl_dir) 339 | d("dl raw files") 340 | ; update count 341 | count_file_name := "v" remote_version ".txt" 342 | remote_update_count_file := OneQuick.remote_update_dl_dir count_file_name 343 | update_count_file := OneQuick._Update_bkp_DIR count_file_name 344 | ErrorLevel := File.Download(remote_update_count_file, update_count_file) 345 | d("dl count, error: " ErrorLevel) 346 | FileDelete, % update_count_file 347 | d("del count") 348 | ; backup 349 | OneQuick._update_copy_file(obj, "", backup_dir) 350 | ; Copy back 351 | d("[CAUTION] DEBUG mode: source code will be changed.") 352 | OneQuick._update_copy_file(obj, dl_dir, "") 353 | ; delete dl 354 | FileRemoveDir, % dl_dir, 1 355 | ; reload 356 | OneQuick.SetConfig("update_from_version", this_version) 357 | RunWait autohotkey.exe %A_ScriptFullPath% 358 | ; only if restart fail 359 | ; if reload onequick fail, will rollback 360 | OneQuick.SetConfig("update_from_version", "") 361 | msg := lang("update_error") 362 | m(msg) 363 | OneQuick._update_copy_file(obj, backup_dir, "") 364 | FileRemoveDir, % backup_dir, 1 365 | } 366 | 367 | _ZIP_OneQuick_self() 368 | { 369 | zip_file_ne := "OneQuick.v" OneQuick.versionObj["version"] 370 | FileDelete, % zip_file_ne ".exe" 371 | FileDelete, % zip_file_ne ".zip" 372 | rar_exe := OneQuick.versionObj["winrar-path"] 373 | zip_file_list := OneQuick.versionObj["zip-path-list"] 374 | cmd = %rar_exe% a %zip_file_ne%.zip %zip_file_list% 375 | run(cmd) 376 | } 377 | 378 | _new_version_info(thisVerObj, remoteVerObj) 379 | { 380 | this_version := thisVerObj["version"] 381 | remote_version := remoteVerObj["version"] 382 | version_compare := this._version_compare(remote_version, this_version) 383 | if(version_compare > 0) 384 | { 385 | remote_desc1 := remoteVerObj["desc-major"] 386 | remote_desc2 := remoteVerObj["desc-minor"] 387 | remote_desc3 := remoteVerObj["desc-revision"] 388 | StringReplace, remote_desc1, % remote_desc1, ``n, `n, All 389 | StringReplace, remote_desc2, % remote_desc2, ``n, `n, All 390 | StringReplace, remote_desc3, % remote_desc3, ``n, `n, All 391 | update_msg := "v" this_version " -> v" remote_version 392 | update_msg .= "`n`n" lang("update_desc") 393 | if(version_compare==1) { 394 | update_msg .= "`n" remote_desc1 395 | } 396 | else if(version_compare==2) { 397 | update_msg .= "`n" remote_desc2 398 | } 399 | else if(version_compare==3) { 400 | update_msg .= "`n" remote_desc3 401 | } 402 | return % update_msg 403 | } 404 | else { 405 | return "" 406 | } 407 | } 408 | 409 | ; update 410 | _debug_version() 411 | { 412 | ; onequick._debug_version 413 | fake_type := 1 414 | ; fake remote 415 | if(fake_type==1) { 416 | fake_version := {"version": "0.9.3" 417 | ,"desc-major": "超级无敌大更新1`n123" 418 | ,"desc-minor": "超级无敌大更新2`n456" 419 | ,"desc-revision": "超级无敌大更新3`n789" } 420 | m(this._new_version_info(this.versionObj, fake_version)) 421 | } 422 | ; fake local 423 | else if (fake_type==2) { 424 | fake_version := {"version": "0.0.0" 425 | ,"desc-major": "will-not-show" 426 | ,"desc-minor": "will-not-show" 427 | ,"desc-revision": "will-not-show" } 428 | m(this._new_version_info(fake_version, this.versionObj)) 429 | } 430 | } 431 | 432 | _version_bigger(ver1, ver2) 433 | { 434 | if(this._version_compare(ver1, ver2) > 0) { 435 | return ver1 436 | } 437 | else { 438 | Return ver2 439 | } 440 | } 441 | 442 | _version_compare(ver1, ver2) 443 | { 444 | pos := OneQuick._version_first_larger(ver1, ver2) 445 | if(pos > 0) { 446 | return % pos 447 | } 448 | else { 449 | neg := OneQuick._version_first_larger(ver2, ver1) 450 | if (neg > 0) { 451 | return % -neg 452 | } 453 | } 454 | return 0 455 | } 456 | 457 | _version_first_larger(version1, version2) 458 | { 459 | ver1 := StrSplit(version1, ".") 460 | ver2 := StrSplit(version2, ".") 461 | if(ver1[1] > ver2[1]) { 462 | return 1 463 | } 464 | else if(ver1[1] = ver2[1]) { 465 | if(ver1[2] > ver2[2]) { 466 | return 2 467 | } 468 | else if(ver1[2] = ver2[2]) { 469 | if(ver1[3] > ver2[3]) { 470 | return 3 471 | } 472 | } 473 | } 474 | return 0 475 | } 476 | 477 | _update_copy_file(listObj, sourcePath, destPath) 478 | { 479 | Loop, % listObj.MaxIndex() 480 | { 481 | path := listObj[A_Index]["name"] 482 | source := sourcePath path 483 | dest := destPath path 484 | if(RegExMatch(source, "^https?://")) { 485 | StringReplace, source, % source, \, /, All 486 | File.Download(source, dest) 487 | } 488 | else { 489 | StringReplace, source, % source, /, \, All 490 | StringReplace, dest, % dest, /, \, All 491 | File.Copy(source, dest, 1) 492 | } 493 | } 494 | } 495 | 496 | _clear_bkp_folders(nlimit="") 497 | { 498 | if(nlimit="") { 499 | nlimit := OneQuick.Bkp_limit 500 | } 501 | bkp_folders := [] 502 | ; count bkp 503 | Loop Files, % OneQuick._Update_bkp_DIR OneQuick._Update_bkp_folder_prefix "*", D 504 | { 505 | bkp_folders.Insert(A_LoopFileFullPath) 506 | } 507 | ; delete bkp 508 | Loop, % bkp_folders.MaxIndex() + 1 - nlimit 509 | { 510 | FileRemoveDir, % OneQuick._Update_bkp_DIR bkp_folders[A_Index], 1 511 | } 512 | } 513 | 514 | ; update list local 515 | _reGenerate_update_list() 516 | { 517 | obj := OneQuick.Generate_update_list() 518 | m("update_list.json:`n`n" Yaml_dump(obj)) 519 | } 520 | Generate_update_list() 521 | { 522 | verObj := OneQuick.versionObj 523 | obj_list := OneQuick._yaml_obj_to_list(verObj["update-path"]) 524 | jsonObj := OneQuick._scan_file_list_obj(obj_list) 525 | ; write 526 | FileDelete, % OneQuick.update_list_path 527 | FileAppend, % JSON.stringify(jsonObj) "`n", % OneQuick.update_list_path 528 | return jsonObj 529 | } 530 | _yaml_obj_to_list(obj) 531 | { 532 | ret_list := [] 533 | Loop, % obj.() 534 | { 535 | ret_list.Insert(obj.(A_Index)) 536 | } 537 | return ret_list 538 | } 539 | _scan_file_list_obj(scan_array) 540 | { 541 | file_list := [] 542 | Loop, % scan_array.MaxIndex() 543 | { 544 | scan_array[A_Index] := StrReplace(scan_array[A_Index], "/", "\") 545 | } 546 | ; adding all 547 | Loop, % scan_array.MaxIndex() 548 | { 549 | path := scan_array[A_Index] 550 | if(SubStr(path, 1, 1)!="!") { 551 | para := InStr(path, "*") ? "FR" : "F" 552 | Loop Files, % path, %para% 553 | { 554 | file_list.Insert(A_LoopFileFullPath) 555 | } 556 | } 557 | } 558 | ; remove ! 559 | Loop, % scan_array.MaxIndex() 560 | { 561 | path := scan_array[A_Index] 562 | if(SubStr(path, 1, 1)="!") { 563 | path := SubStr(path, 2) 564 | Loop Files, % path, FR 565 | { 566 | file_list := xArray.remove(file_list, A_LoopFileFullPath) 567 | } 568 | } 569 | } 570 | ; implement obj 571 | obj := [] 572 | Loop, % file_list.MaxIndex() 573 | { 574 | item := {"name": file_list[A_Index]} 575 | obj.Insert(item) 576 | } 577 | return obj 578 | } 579 | GetBiggerRemVersion() 580 | { 581 | this_version := this.versionObj["version"] 582 | rem_version := this.GetConfig("remote_version") 583 | ver := this._version_bigger(this_version, rem_version) 584 | if(this_version=ver) { 585 | return "" 586 | } 587 | else { 588 | return % ver 589 | } 590 | } 591 | 592 | ; tray icon 593 | SetIcon(ico) 594 | { 595 | Tray.SetIcon(ico) 596 | } 597 | ; callback register 598 | OnExit(func) 599 | { 600 | this.OnExitCmd.Insert(func) 601 | } 602 | 603 | OnClipboardChange(func) 604 | { 605 | this.OnClipboardChangeCmd.Insert(func) 606 | } 607 | 608 | OnPause(func) 609 | { 610 | this.OnPauseCmd.Insert(func) 611 | } 612 | 613 | OnSuspend(func) 614 | { 615 | this.OnSuspendCmd.Insert(func) 616 | } 617 | 618 | ; feature.yaml 619 | GetFeatureCfg(keyStr, default="") 620 | { 621 | keyArray := StrSplit(keyStr, ".") 622 | obj := OneQuick.FeatureObj 623 | Loop, % keyArray.MaxIndex()-1 624 | { 625 | cur_key := keyArray[A_Index] 626 | obj := obj[cur_key] 627 | } 628 | cur_key := keyArray[keyArray.MaxIndex()] 629 | if(obj[cur_key]=="") 630 | { 631 | return default 632 | } 633 | return obj[cur_key] 634 | } 635 | 636 | Edit_feature_yaml() 637 | { 638 | if(OneQuick._DEBUG_ && this.debugConfig("load_default_feature_yaml", 0)) { 639 | OneQuick.Edit(OneQuick.feature_yaml_default_file) 640 | } 641 | else { 642 | OneQuick.Edit(OneQuick.feature_yaml_file) 643 | } 644 | } 645 | 646 | LoadFeatureYaml() 647 | { 648 | if(OneQuick._DEBUG_ && this.debugConfig("load_default_feature_yaml", 0)) { 649 | OneQuick.FeatureObj := Yaml(OneQuick.feature_yaml_default_file) 650 | } 651 | else { 652 | if(!FileExist(this.feature_yaml_file)) { 653 | FileCopy, % this.feature_yaml_default_file, % this.feature_yaml_file, 0 654 | } 655 | OneQuick.FeatureObj := Yaml(OneQuick.feature_yaml_file) 656 | } 657 | } 658 | ; config.ini 659 | debugConfig(key, default) 660 | { 661 | return OneQuick.GetConfig(key, default, "debug", OneQuick._DEBUG_) 662 | } 663 | 664 | GetConfig(key, default="", section="onequick", autoWrite=true) 665 | { 666 | IniRead, output, % OneQuick.config_file, % section, % key 667 | if(output=="ERROR") 668 | { 669 | if(autoWrite) { 670 | OneQuick.SetConfig(key, default, section) 671 | } 672 | return default 673 | } 674 | return output 675 | } 676 | 677 | SetConfig(key, value, section="onequick") 678 | { 679 | IniWrite, % value, % OneQuick.config_file, % section, % key 680 | } 681 | 682 | ; user data 683 | SaveUserData() 684 | { 685 | if(!FileExist(this._JSON_DIR)) { 686 | FileCreateDir, % this._JSON_DIR 687 | } 688 | FileDelete, % this.user_data_file 689 | FileAppend % JSON.stringify(OneQuick.UserData), % this.user_data_file 690 | } 691 | 692 | LoadUserData() 693 | { 694 | FileRead, str, % this.user_data_file 695 | obj := JSON.parse(str) 696 | if(IsObject(obj)) 697 | OneQuick.UserData := obj 698 | Else 699 | OneQuick.UserData := [] 700 | } 701 | 702 | ; 703 | ; run inputbox 704 | Command_run() 705 | { 706 | Gui +LastFound +OwnDialogs +AlwaysOnTop 707 | msg := lang("input_command_run") 708 | InputBox, cmd, OneQuick Command Run, % msg, , 330, 150 709 | if !ErrorLevel 710 | run(cmd) 711 | } 712 | 713 | Edit(filename, admin := 0) 714 | { 715 | if not FileExist(filename) 716 | { 717 | m("Can't find " filename "") 718 | Return 719 | } 720 | if ((not A_IsAdmin) && admin) 721 | { 722 | cmd := this.Editor " """ filename """" 723 | Run *RunAs %cmd% 724 | } 725 | Else 726 | { 727 | cmd := this.Editor " """ filename """" 728 | Run % cmd 729 | } 730 | } 731 | 732 | ; Tray Menu 733 | Update_Tray_Menu() 734 | { 735 | version_str := lang("About") " v" this.versionObj["version"] 736 | autorun := OneQuick.GetConfig("autorun", 0) 737 | autoupdate := OneQuick.GetConfig("auto_update", 0) 738 | bigVer := OneQuick.GetBiggerRemVersion() 739 | if(bigVer!="") { 740 | check_update_name := lang("! New Version !") " v" bigVer 741 | } 742 | else { 743 | check_update_name := lang("Check Update") 744 | } 745 | lang := OneQuick.GetConfig("lang") 746 | Menu, Tray, Tip, % this.ProgramName 747 | xMenu.New("TrayLanguage" 748 | ,[["English", "OneQuick.SetLang", {check: lang=="en"}] 749 | , ["中文", "OneQuick.SetLang", {check: lang=="cn"}]]) 750 | xMenu.New("TrayAdvanced" 751 | ,[["Suspend Hotkey", "OneQuick.SetSuspend", {check: A_IsSuspended}] 752 | ,["Pause Thread", "OneQuick.SetPause", {check: A_IsPaused}] 753 | ,[] 754 | ,[lang("AHK Standard Menu"), "OneQuick.Standard_Tray_Menu", {check: OneQuick._switch_tray_standard_menu}] 755 | ,[] 756 | ,[lang("Reset Program"), "OneQuick.ResetProgram"]]) 757 | TrayMenuList := [] 758 | debug_show := OneQuick.debugConfig("show", 0) 759 | if(OneQuick._DEBUG_||debug_show) { 760 | TrayMenuList := xArray.merge(TrayMenuList 761 | ,[["DEBUG Mode: " (OneQuick._DEBUG_?"ON":"OFF"), "OneQuick.debug_mode"],[]]) 762 | } 763 | if(OneQuick._DEBUG_) { 764 | TrayMenuList := xArray.merge(TrayMenuList 765 | ,[["ZIP files", "OneQuick._ZIP_OneQuick_self"] 766 | ,["Generate_update_list.json", "OneQuick._reGenerate_update_list"] 767 | ,["Count_Download_Online", "OneQuick._SumGithubDownloadCount"] 768 | ,[] 769 | ,["config.ini", "notepad " OneQuick.config_file] 770 | ,["core.ahk", "edit: script/OneQuick.Core.ahk"] 771 | ,["version.yaml", "edit:" OneQuick.version_yaml_file] 772 | ,[]]) 773 | } 774 | TrayMenuList := xArray.merge(TrayMenuList 775 | ,[[version_str, "OneQuick.About"] 776 | ,[lang("help_online"), OneQuick.remote_help] 777 | ,[check_update_name, "OneQuick.Check_update"] 778 | ,[] 779 | ,[lang("Autorun"), "OneQuick.SetAutorun", {check: autorun}] 780 | ,[lang("AutoUpdate"), "OneQuick.SetAutoUpdate", {check: autoupdate}] 781 | ,["Language",, {"sub": "TrayLanguage"}] 782 | ,[lang("Advanced"),, {"sub": "TrayAdvanced"}] 783 | ,[] 784 | ,[lang("Disable"), "OneQuick.SetDisable", {check: A_IsPaused&&A_IsSuspended}] 785 | ,[lang("Reload"), "OneQuick.Reload"] 786 | ,[lang("Exit"), "OneQuick.Exit"] 787 | ,[] 788 | ,[lang("Open AutoHotkey.exe Folder"), "Sub_OneQuick_EXE_Loc"] 789 | ,[lang("AutoHotKey Help"), "Sub_OneQuick_AHKHelp"] 790 | ,[] 791 | ,[lang("Open OneQuick Folder"), A_WorkingDir] 792 | ,[lang("Edit Ext.ahk"), "edit:" OneQuick.Ext_ahk_file] 793 | ,[lang("Edit feature.yaml"), "OneQuick.Edit_feature_yaml"] ]) 794 | Tray.SetMenu(TrayMenuList, OneQuick._switch_tray_standard_menu) 795 | Menu, Tray, Default, % lang("Disable") 796 | Menu, Tray, Click, 1 797 | OneQuick.Update_Icon() 798 | } 799 | static _switch_tray_standard_menu := 0 800 | Standard_Tray_Menu(act="toggle") 801 | { 802 | OneQuick._switch_tray_standard_menu := (act="toggle")? !OneQuick._switch_tray_standard_menu :act 803 | OneQuick.Update_Tray_Menu() 804 | } 805 | Update_Icon() 806 | { 807 | setsuspend := A_IsSuspended 808 | setpause := A_IsPaused 809 | if !setpause && !setsuspend { 810 | this.SetIcon(this.icon_default) 811 | } 812 | Else if !setpause && setsuspend { 813 | this.SetIcon(this.icon_pause) 814 | } 815 | Else if setpause && !setsuspend { 816 | this.SetIcon(this.icon_suspend) 817 | } 818 | Else if setpause && setsuspend { 819 | this.SetIcon(this.icon_suspend_pause) 820 | } 821 | } 822 | SetState(setsuspend="", setpause="") 823 | { 824 | setsuspend := (setsuspend="")? A_IsSuspended: setsuspend 825 | setpause := (setpause="")? A_IsPaused: setpause 826 | if(!A_IsSuspended && setsuspend) { 827 | RunArr(OneQuick.OnSuspendCmd) 828 | } 829 | if(!A_IsPaused && setpause) { 830 | RunArr(OneQuick.OnPauseCmd) 831 | } 832 | if(setsuspend) { 833 | Suspend, On 834 | } 835 | else { 836 | Suspend, Off 837 | } 838 | if(setpause) { 839 | Pause, On, 1 840 | } 841 | else { 842 | Pause, Off 843 | } 844 | OneQuick.Update_Tray_Menu() 845 | } 846 | ; 847 | About() 848 | { 849 | lang := OneQuick.GetConfig("lang", "cn") 850 | Gui, OneQuick_About: New 851 | Gui OneQuick_About:+Resize +AlwaysOnTop +MinSize400 -MaximizeBox -MinimizeBox 852 | Gui, Font, s12 853 | s := "OneQuick v" OneQuick.versionObj["version"] 854 | Gui, Add, Text,, % s 855 | s := "" lang("Home Page") "" 856 | Gui, Add, Link,, % s 857 | s := "" lang("Feedback") "" 858 | Gui, Add, Link,, % s 859 | s := "Author: XJK jack8461@msn.cn" 860 | Gui, Add, Link,, % s 861 | dnt := lang="cn" ? "捐赠" : "Donate!" 862 | s := "" dnt "" 863 | s .= " 去知乎点赞!" 864 | Gui, Add, Link,, % s 865 | Gui, Add, Text 866 | Gui, Add, Button, Default gSub_Close_OneQuick_About, Close 867 | GuiControl, Focus, Close 868 | Gui, Show,, About OneQuick 869 | } 870 | ; OneQuick._SumGithubDownloadCount 871 | _SumGithubDownloadCount() 872 | { 873 | json_str := http.get("https://api.github.com/repos/XUJINKAI/OneQuick/releases") 874 | obj := JSON.Parse(json_str) 875 | sum := 0 876 | msg := "" 877 | Loop, % obj.MaxIndex() 878 | { 879 | rel := obj[A_Index] 880 | tag_name := rel["tag_name"] 881 | assets := rel["assets"] 882 | msg .= "`n" tag_name ":" 883 | Loop, % assets.MaxIndex() 884 | { 885 | file := assets[A_Index] 886 | name := file["name"] 887 | dlcount := file["download_count"] 888 | sum += dlcount 889 | msg .= "`n " name ": " dlcount 890 | } 891 | } 892 | msg := "github download sum: " sum msg 893 | m(msg) 894 | } 895 | Reload() 896 | { 897 | Reload 898 | } 899 | ResetProgram() 900 | { 901 | lang := OneQuick.GetConfig("lang") 902 | msg := lang="cn" ? "重置会删除config.ini, OneQuick.feature.yaml并重启OneQuick." : "Reset program will delete config.ini, OneQuick.feature.yaml,`nAnd reload OneQuick." 903 | if(mq(msg, 0x1124)) { 904 | FileDelete, config.ini 905 | FileDelete, OneQuick.feature.yaml 906 | OneQuick.Reload() 907 | } 908 | } 909 | Exit(show_msg=true) 910 | { 911 | if(mq(lang("exit_msg"), 0x1134)) { 912 | ExitApp 913 | } 914 | } 915 | SetDisable(act="toggle") 916 | { 917 | setdisable := (act="toggle")? !(A_IsPaused&&A_IsSuspended): act 918 | OneQuick.SetState(setdisable, setdisable) 919 | } 920 | ; hotkey 921 | SetSuspend(act="toggle") 922 | { 923 | setsuspend := (act="toggle")? !A_IsSuspended: act 924 | OneQuick.SetState(setsuspend, A_IsPaused) 925 | } 926 | ; thread 927 | SetPause(act="toggle") 928 | { 929 | setpause := (act="toggle")? !A_IsPaused: act 930 | OneQuick.SetState(A_IsSuspended, setpause) 931 | } 932 | 933 | SetAutorun(act="toggle") 934 | { 935 | cfg := OneQuick.GetConfig("autorun", 0) 936 | autorun := (act="config")? cfg :act 937 | autorun := (act="toggle")? !cfg :autorun 938 | Regedit.Autorun(autorun, OneQuick.ProgramName, OneQuick.Launcher_Name) 939 | OneQuick.SetConfig("autorun", autorun) 940 | if(autorun) 941 | { 942 | Menu, Tray, Check, % lang("Autorun") 943 | } 944 | Else 945 | { 946 | Menu, Tray, UnCheck, % lang("Autorun") 947 | } 948 | } 949 | 950 | SetAutoUpdate(act="toggle") 951 | { 952 | cfg := OneQuick.GetConfig("auto_update", 0) 953 | au := (act="toggle") ?!cfg :act 954 | OneQuick.SetConfig("auto_update", au) 955 | if(au) 956 | { 957 | Menu, Tray, Check, % lang("AutoUpdate") 958 | OneQuick.Check_update(false) 959 | } 960 | Else 961 | { 962 | Menu, Tray, UnCheck, % lang("AutoUpdate") 963 | } 964 | } 965 | 966 | debug_mode(act="toggle") 967 | { 968 | debug := (act="toggle") ? !OneQuick._DEBUG_ :act 969 | OneQuick.SetConfig("debug", debug, "debug") 970 | OneQuick.Reload() 971 | } 972 | 973 | SetLang(act="itemname") 974 | { 975 | if(act="itemname") 976 | { 977 | lang_map := {"English": "en", "中文": "cn"} 978 | lang := lang_map[A_ThisMenuItem] 979 | } 980 | else { 981 | lang := act 982 | } 983 | OneQuick.SetConfig("lang", lang) 984 | OneQuick.Reload() 985 | } 986 | 987 | } 988 | 989 | ; event callback 990 | OnClipboardChange: 991 | RunArr(OneQuick.OnClipboardChangeCmd) 992 | Return 993 | 994 | Sub_OnExit: 995 | RunArr(OneQuick.OnExitCmd) 996 | OneQuick.SaveUserData() 997 | ExitApp 998 | 999 | ; -------------------------- 1000 | SUB_VOID: 1001 | Return 1002 | 1003 | Sub_Close_OneQuick_About: 1004 | Gui, Cancel 1005 | Return 1006 | 1007 | Sub_Auto_Check_update: 1008 | SetTimer, Sub_Auto_Check_update, % -OneQuick.check_update_period 1009 | OneQuick.Check_update(false) 1010 | return 1011 | 1012 | Sub_OneQuick_AHKHelp: 1013 | splitpath, a_ahkpath, , dir 1014 | helpfile := % dir "\AutoHotKey.chm" 1015 | if FileExist(helpfile){ 1016 | run(helpfile) 1017 | } 1018 | Else{ 1019 | m("Can't find help file.") 1020 | } 1021 | Return 1022 | 1023 | Sub_OneQuick_EXE_Loc: 1024 | splitpath, a_ahkpath, , dir 1025 | run(dir) 1026 | Return 1027 | 1028 | ; ////////////////////////////////////////////////////////////////////////// 1029 | ; ////////////////////////////////////////////////////////////////////////// 1030 | ; ////////////////////////////////////////////////////////////////////////// 1031 | ; ////////////////////////////////////////////////////////////////////////// 1032 | ; ////////////////////////////////////////////////////////////////////////// 1033 | ; ////////////////////////////////////////////////////////////////////////// 1034 | 1035 | lang(key, default="") 1036 | { 1037 | lang := OneQuick.GetConfig("lang", OneQuick.Default_lang) 1038 | lang_file := OneQuick._LANG_DIR "" lang ".ini" 1039 | FileEncoding 1040 | IniRead, out, % lang_file, lang, % key, %A_Space% 1041 | if(out=="") { 1042 | if(lang!="en"||default!="") 1043 | IniWrite,%A_Space%, % lang_file, lang, % key 1044 | if(default=="") 1045 | out := key 1046 | else 1047 | out := default 1048 | } 1049 | return out 1050 | } 1051 | 1052 | class xArray 1053 | { 1054 | ; xArray.merge 1055 | merge(arr1, arr2) 1056 | { 1057 | Loop, % arr2.MaxIndex() 1058 | { 1059 | arr1.Insert(arr2[A_Index]) 1060 | } 1061 | return % arr1 1062 | } 1063 | ; xArray.remove 1064 | remove(arr, value) 1065 | { 1066 | Loop, % arr.MaxIndex() 1067 | { 1068 | if(arr[A_Index]=value) { 1069 | arr.RemoveAt(A_Index) 1070 | return % xArray.remove(arr, value) 1071 | } 1072 | } 1073 | return % arr 1074 | } 1075 | } 1076 | 1077 | class http 1078 | { 1079 | get(url) 1080 | { 1081 | try 1082 | { 1083 | oHttp := ComObjCreate("WinHttp.Winhttprequest.5.1") 1084 | oHttp.open("GET", url) 1085 | oHttp.send() 1086 | return % oHttp.responseText 1087 | } 1088 | catch e 1089 | { 1090 | return "" 1091 | } 1092 | } 1093 | } 1094 | 1095 | class File 1096 | { 1097 | CreateDir(path) 1098 | { 1099 | if(path="") { 1100 | Return 1101 | } 1102 | StringReplace, path, % path, /, \, All 1103 | if(FileExist(path)) { 1104 | return 1105 | } 1106 | SplitPath, % path,, OutDir 1107 | if(OutDir!="" && !FileExist(OutDir)) { 1108 | File.CreateDir(OutDir) 1109 | } 1110 | FileCreateDir, % path 1111 | } 1112 | 1113 | ; File.Download 1114 | Download(url, path) 1115 | { 1116 | SplitPath, % path, , OutDir 1117 | File.CreateDir(OutDir) 1118 | UrlDownloadToFile, % url, % path 1119 | return ErrorLevel 1120 | } 1121 | 1122 | Append(content, path) 1123 | { 1124 | SplitPath, % path, , OutDir 1125 | File.CreateDir(OutDir) 1126 | FileAppend, % content, % path 1127 | } 1128 | 1129 | Copy(SourcePattern, DestPattern, Flag = 0) 1130 | { 1131 | IfNotExist, % SourcePattern 1132 | return -1 1133 | SplitPath, % DestPattern, , OutDir 1134 | File.CreateDir(OutDir) 1135 | FileCopy, % SourcePattern, % DestPattern, % Flag 1136 | return ErrorLevel 1137 | } 1138 | } 1139 | 1140 | class Tray 1141 | { 1142 | ; Tray.Tip 1143 | Tip(msg, seconds=1, opt=0x1) 1144 | { 1145 | ; //BUG traytip弹出后,第一次单击托盘图标的动作将失效,第二次单击或显示托盘菜单后正常 1146 | TrayTip, % OneQuick.ProgramName, % msg, % seconds, % opt 1147 | Return 1148 | title := OneQuick.ProgramName 1149 | cmd = "%A_AhkPath%" "%A_ScriptDir%\OneQuick.Core.ahk" -traytip "%title%" "%msg%" "%opt%" 1150 | Run, %cmd% 1151 | Return 1152 | } 1153 | 1154 | ; Tray.SetMenu 1155 | SetMenu(menuList, ahk_std_menu=0) 1156 | { 1157 | Menu, Tray, DeleteAll 1158 | if(ahk_std_menu) { 1159 | Menu, Tray, Standard 1160 | Menu, Tray, Add 1161 | } 1162 | else { 1163 | Menu, Tray, NoStandard 1164 | } 1165 | xMenu.add("Tray", menuList) 1166 | } 1167 | 1168 | ; Tray.SetIcon 1169 | SetIcon(path) 1170 | { 1171 | if(FileExist(path)) 1172 | Menu, Tray, Icon, %path%,,1 1173 | } 1174 | } 1175 | 1176 | class Regedit 1177 | { 1178 | static Subkey_Autorun := "Software\Microsoft\Windows\CurrentVersion\Run" 1179 | ; Regedit.Autorun 1180 | Autorun(switch, name, path="") 1181 | { 1182 | if(switch) 1183 | { 1184 | RegWrite, REG_SZ, HKCU, % Regedit.Subkey_Autorun, % name, % path 1185 | } 1186 | Else 1187 | { 1188 | RegDelete, HKCU, % Regedit.Subkey_Autorun, % name 1189 | } 1190 | } 1191 | ; Regedit.IsAutorun 1192 | IsAutorun(name, path) 1193 | { 1194 | RegRead, output, HKCU, % Regedit.Subkey_Autorun, % name 1195 | return % output==path 1196 | } 1197 | } 1198 | 1199 | ; ////////////////////////////////////////////////////////////////////////// 1200 | ; ////////////////////////////////////////////////////////////////////////// 1201 | ; ////////////////////////////////////////////////////////////////////////// 1202 | /* 1203 | a clipboard enhance class, provide a clipboard history list & quick search menu 1204 | 1205 | 1. you can use "xClipboard.SetHotkey(allClips, copyAndShow, clipMenu)" function to set hotkeys, 1206 | parameters are hotkey name, 1207 | "allClips" means open clipboard history list, 1208 | "clipMenu" means show current clipboard content and quick search menu, 1209 | "copyAndShow" will do a copy action (^c) and then show "clipMenu" 1210 | ps.it is strongly recommended to Sethotkey as ("^+x", "^+c", "^+v") 1211 | 1212 | 2. use "xClipboard.SetSearchList" function to define quick search menu 1213 | e.g.xClipboard.SetSearchList([["g","Google","https://www.google.com/search?q=%s"],[...]]) 1214 | means use "Google" search current clipboard when Press "g" 1215 | "%s" in url will be instead of current clipboard text 1216 | */ 1217 | class xClipboard 1218 | { 1219 | static ClsName := "clipboard" 1220 | static ini_registered := 0 1221 | static Clips := [] 1222 | static FavourClips := [] 1223 | static BrowserArr := [] 1224 | static BrowserItemName := "" 1225 | static SearchArr := [] 1226 | static ClipsFirstShowNum = 1227 | static ClipsTotalNum = 1228 | 1229 | Ini() 1230 | { 1231 | if (this.ini_registered == 1) 1232 | Return 1233 | OneQuick.OnClipboardChange("Sub_xClipboard_OnClipboardChange") 1234 | OneQuick.OnExit("Sub_xClipboard_OnExit") 1235 | this.Clips := OneQuick.UserData["xClipboard_Clips"] 1236 | this.FavourClips := OneQuick.UserData["xClipboard_FavourClips"] 1237 | this.ClipsFirstShowNum := OneQuick.GetFeatureCfg("clipboard.ClipsFirstShowNum", 10) 1238 | this.ClipsTotalNum := OneQuick.GetFeatureCfg("clipboard.ClipsTotalNum", 50) 1239 | if not IsObject(this.Clips) 1240 | this.Clips := [] 1241 | if not IsObject(this.FavourClips) 1242 | this.FavourClips := [] 1243 | this.ini_registered := 1 1244 | } 1245 | 1246 | SetHotkey(allClips, copyAndShow, clipMenu) 1247 | { 1248 | if (allClips != "") 1249 | Hotkey, %allClips%, Sub_xClipboard_ShowAllClips 1250 | if (copyAndShow != "") 1251 | Hotkey, %copyAndShow%, Sub_xClipboard_CopyAndShowMenu 1252 | if (clipMenu != "") 1253 | Hotkey, %clipMenu%, Sub_xClipboard_ShowClipMenu 1254 | } 1255 | 1256 | SetBrowserList(browserList) 1257 | { 1258 | this.BrowserArr := browserList 1259 | if(this.BrowserArr.MaxIndex()) 1260 | { 1261 | this.BrowserItemName := this.BrowserArr[1][2] "`t&" this.BrowserArr[1][1] 1262 | OneQuick.Browser := this.BrowserArr[1][3] 1263 | } 1264 | } 1265 | 1266 | _setBrowserByItemName(ItemName) 1267 | { 1268 | if(RegExMatch(ItemName, "^([^`t]+)", out)) 1269 | { 1270 | Loop, % this.BrowserArr.MaxIndex() 1271 | { 1272 | if(this.BrowserArr[A_Index][2] == out) 1273 | { 1274 | this.BrowserItemName := ItemName 1275 | OneQuick.Browser := this.BrowserArr[A_Index][3] 1276 | } 1277 | } 1278 | } 1279 | } 1280 | 1281 | SetSearchList(search) 1282 | { 1283 | this.SearchArr := search 1284 | } 1285 | 1286 | ShowAllClips() 1287 | { 1288 | Try 1289 | { 1290 | Menu, xClipboard_AllclipsMenu, DeleteAll 1291 | } 1292 | Try 1293 | { 1294 | Menu, xClipboard_AllclipsMenu_More, DeleteAll 1295 | } 1296 | Try 1297 | { 1298 | Menu, xClipboard_AllclipsMenu_Favour, DeleteAll 1299 | } 1300 | ClipsCount := this.Clips.MaxIndex() 1301 | Loop, % ClipsCount 1302 | { 1303 | idx := ClipsCount - A_Index + 1 1304 | keyName := this.Clips[idx][2] 1305 | if (A_Index <= this.ClipsFirstShowNum) 1306 | Menu, xClipboard_AllclipsMenu, Add, % (A_Index<10?"&":"") A_Index ". " keyName, Sub_xClipboard_AllClips_Click 1307 | Else 1308 | Menu, xClipboard_AllclipsMenu_More, Add, % A_Index ". " keyName, Sub_xClipboard_AllClips_MoreClick 1309 | } 1310 | if (ClipsCount >= this.ClipsFirstShowNum) 1311 | Menu, xClipboard_AllclipsMenu, Add, % lang("More Clips"), :xClipboard_AllclipsMenu_More 1312 | FavoursCount := this.FavourClips.MaxIndex() 1313 | if (FavoursCount >= 0) 1314 | { 1315 | Loop, % FavoursCount 1316 | { 1317 | idx := FavoursCount - A_Index + 1 1318 | keyName := this.FavourClips[idx][2] 1319 | Menu, xClipboard_AllclipsMenu_Favour, Add, % A_Index ". " keyName, Sub_xClipboard_AllClips_FavourClick 1320 | } 1321 | Menu, xClipboard_AllclipsMenu_Favour, Add 1322 | Menu, xClipboard_AllclipsMenu_Favour, Add, % lang("Clear Favour List"), Sub_xClipboard_AllClips_FavourClear 1323 | Menu, xClipboard_AllclipsMenu, Add, % lang("Favour Clips"), :xClipboard_AllclipsMenu_Favour 1324 | } 1325 | if (ClipsCount > 0) 1326 | { 1327 | Menu, xClipboard_AllclipsMenu, Add 1328 | Menu, xClipboard_AllclipsMenu, Add, % lang("Paste All"), Sub_Menu_xClipboard_PasteAll 1329 | Menu, xClipboard_AllclipsMenu, Add 1330 | Menu, xClipboard_AllclipsMenu, Add, % lang("Clear Clipboard") "(" %ClipsCount% " clips)", Sub_Menu_xClipboard_DeleteAll 1331 | } 1332 | Else 1333 | { 1334 | Menu, xClipboard_AllclipsMenu, Add, % lang("Clear Clipboard") " (0 clips)", Sub_Menu_xClipboard_DeleteAll 1335 | } 1336 | Menu, xClipboard_AllclipsMenu, Show 1337 | } 1338 | 1339 | CopyAndShowMenu() 1340 | { 1341 | send ^c 1342 | clipwait 1343 | sleep 100 1344 | this.ShowClipMenu() 1345 | } 1346 | 1347 | ShowClipMenu(str := "") 1348 | { 1349 | if (str != "") 1350 | { 1351 | Clipboard := str 1352 | Sleep, 100 1353 | } 1354 | if (Clipboard == "") 1355 | Return 1356 | Try 1357 | { 1358 | Menu, xClipboard_clipMenu, DeleteAll 1359 | } 1360 | cliptrim := this._Trim(Clipboard, 0) 1361 | Menu, xClipboard_clipMenu, Add, % cliptrim, Sub_xClipboard_ClipMenu_CLIPTitle 1362 | Menu, xClipboard_clipMenu, Disable, % cliptrim 1363 | Menu, xClipboard_clipMenu, Add, % lang("Paste (Tab)") "`t&`t", Sub_xClipboard_ClipMenu_Paste 1364 | Menu, xClipboard_clipMenu, Add, % lang("RUN in CMD (Space)") " `t& ", Sub_xClipboard_ClipMenu_CMD 1365 | Menu, xClipboard_clipMenu, Add 1366 | Loop, % this.SearchArr.MaxIndex() 1367 | { 1368 | xC_Ssubobj := this.SearchArr[A_Index] 1369 | xC_item := xC_Ssubobj[2] ((xC_Ssubobj[1]=="")?"":"`t&" xC_Ssubobj[1]) 1370 | Menu, xClipboard_clipMenu, Add, % xC_item, Sub_xClipboard_ClipCmdMenu_Search 1371 | } 1372 | if(this.BrowserArr.MaxIndex()) 1373 | { 1374 | Menu, xClipboard_clipMenu, Add 1375 | Loop, % this.BrowserArr.MaxIndex() 1376 | { 1377 | subobj := this.BrowserArr[A_Index] 1378 | Menu, xClipboard_clipMenu, Add, % subobj[2] "`t&" subobj[1], Sub_xClipboard_ClipCmdMenu_SetBrowser 1379 | } 1380 | if(this.BrowserItemName != "") 1381 | { 1382 | Menu, xClipboard_clipMenu, Check, % this.BrowserItemName 1383 | } 1384 | } 1385 | Menu, xClipboard_clipMenu, Add 1386 | Menu, xClipboard_clipMenu, Add, % lang("Add to Favourite"), Sub_xClipboard_ClipMenu_AddFavour 1387 | Menu, xClipboard_clipMenu, Add, % lang("Remove from Favourite"), Sub_xClipboard_ClipMenu_RemoveFavour 1388 | Menu, xClipboard_clipMenu, Add, 1389 | Menu, xClipboard_clipMenu, Add, % lang("Delete"), Sub_xClipboard_ClipMenu_Delete 1390 | Menu, xClipboard_clipMenu, Show 1391 | } 1392 | 1393 | DeleteAllClips() 1394 | { 1395 | this.Clips := [] 1396 | Clipboard = 1397 | } 1398 | 1399 | DeleteAllFavourClips() 1400 | { 1401 | this.FavourClips := [] 1402 | } 1403 | 1404 | _Trim(str_ori, add_time := 1) 1405 | { 1406 | str := Trim(str_ori, " `t`r`n") 1407 | tabfind := InStr(str, "`t") 1408 | if (tabfind > 0) 1409 | { 1410 | str := SubStr(str, 1, tabfind -1) 1411 | } 1412 | if (str == "") 1413 | str := "" 1414 | Else if (SubStr(str, 1, 1) != SubStr(str_ori, 1, 1)) 1415 | str := "_" str 1416 | if StrLen(str) > 50 1417 | str := SubStr(str, 1, 50) 1418 | str := str "`t[" StrLen(str_ori) "]" 1419 | if(add_time) 1420 | { 1421 | str := str "[" A_Hour ":" A_Min ":" A_Sec "]" 1422 | } 1423 | Return % str 1424 | } 1425 | 1426 | _AddArrClip(ByRef Arr, str) 1427 | { 1428 | trim_str := xClipboard._Trim(str) 1429 | if str != 1430 | { 1431 | Loop, % Arr.MaxIndex() 1432 | { 1433 | if (str == Arr[A_Index][1]) 1434 | { 1435 | Arr.Remove(A_Index) 1436 | } 1437 | } 1438 | Arr.Insert([str, trim_str]) 1439 | } 1440 | } 1441 | 1442 | _RemoveArrClip(ByRef Arr, str) 1443 | { 1444 | Loop, % Arr.MaxIndex() 1445 | { 1446 | if (str == Arr[A_Index][1]) 1447 | { 1448 | Arr.Remove(A_Index) 1449 | } 1450 | } 1451 | } 1452 | } 1453 | ; All Clips Menu 1454 | Sub_xClipboard_AllClips_Click: 1455 | idx := xClipboard.Clips.MaxIndex() - A_ThisMenuItemPos + 1 1456 | xClipboard.ShowClipMenu(xClipboard.Clips[idx][1]) 1457 | Return 1458 | 1459 | Sub_xClipboard_AllClips_MoreClick: 1460 | idx := xClipboard.Clips.MaxIndex() - A_ThisMenuItemPos + 1 - xClipboard.ClipsFirstShowNum 1461 | xClipboard.ShowClipMenu(xClipboard.Clips[idx][1]) 1462 | Return 1463 | 1464 | Sub_xClipboard_AllClips_FavourClick: 1465 | idx := xClipboard.FavourClips.MaxIndex() - A_ThisMenuItemPos + 1 1466 | xClipboard.ShowClipMenu(xClipboard.FavourClips[idx][1]) 1467 | Return 1468 | 1469 | Sub_xClipboard_AllClips_FavourClear: 1470 | xClipboard.DeleteAllFavourClips() 1471 | Return 1472 | 1473 | Sub_Menu_xClipboard_PasteAll: 1474 | ClipboardRem := ClipboardAll 1475 | ClipboardPaste = 1476 | Loop, % xClipboard.Clips.MaxIndex() 1477 | { 1478 | ClipboardPaste := ClipboardPaste A_Index "`r`n" xClipboard.Clips[A_Index][1] "`r`n" 1479 | } 1480 | Clipboard := ClipboardPaste 1481 | Send, ^v 1482 | ClipboardPaste = 1483 | Clipboard := ClipboardRem 1484 | ClipboardRem = 1485 | Return 1486 | 1487 | Sub_Menu_xClipboard_DeleteAll: 1488 | xClipboard.DeleteAllClips() 1489 | Return 1490 | 1491 | ; Clip Menu 1492 | Sub_xClipboard_ClipMenu_CLIPTitle: 1493 | Return 1494 | 1495 | Sub_xClipboard_ClipMenu_Paste: 1496 | xC_tmp := % Clipboard 1497 | Clipboard := xC_tmp 1498 | Send, ^v 1499 | Return 1500 | 1501 | Sub_xClipboard_ClipMenu_CMD: 1502 | run(Trim(Clipboard, " `t"), 0) 1503 | Return 1504 | 1505 | Sub_xClipboard_ClipCmdMenu_Search: 1506 | xC_site := xClipboard.SearchArr[A_ThisMenuItemPos-4][3] 1507 | StringReplace, xC_site, xC_site, `%s, % UriEncode(clipboard), All 1508 | Run(xC_site) 1509 | Return 1510 | 1511 | Sub_xClipboard_ClipCmdMenu_SetBrowser: 1512 | xClipboard._setBrowserByItemName(A_ThisMenuItem) 1513 | xClipboard.ShowClipMenu() 1514 | Return 1515 | 1516 | Sub_xClipboard_ClipMenu_Delete: 1517 | xClipboard._RemoveArrClip(xClipboard.Clips, Clipboard) 1518 | if (xClipboard.Clips.MaxIndex() >= 1) 1519 | Clipboard := xClipboard.Clips[1][1] 1520 | Else 1521 | Clipboard = 1522 | Return 1523 | 1524 | Sub_xClipboard_ClipMenu_AddFavour: 1525 | xClipboard._AddArrClip(xClipboard.FavourClips, Clipboard) 1526 | Return 1527 | 1528 | Sub_xClipboard_ClipMenu_RemoveFavour: 1529 | xClipboard._RemoveArrClip(xClipboard.FavourClips, Clipboard) 1530 | Return 1531 | ; hotkey 1532 | Sub_xClipboard_ShowAllClips: 1533 | xClipboard.ShowAllClips() 1534 | Return 1535 | 1536 | Sub_xClipboard_CopyAndShowMenu: 1537 | xClipboard.CopyAndShowMenu() 1538 | Return 1539 | 1540 | Sub_xClipboard_ShowClipMenu: 1541 | xClipboard.ShowClipMenu() 1542 | Return 1543 | 1544 | ; OnEvent 1545 | Sub_xClipboard_OnClipboardChange: 1546 | xClipboard._AddArrClip(xClipboard.Clips, Clipboard) 1547 | while (xClipboard.ClipsTotalNum > 0 && xClipboard.Clips.MaxIndex() > xClipboard.ClipsTotalNum) 1548 | xClipboard.Clips.Remove(1) 1549 | Return 1550 | 1551 | Sub_xClipboard_OnExit: 1552 | OneQuick.UserData["xClipboard_Clips"] := xClipboard.Clips 1553 | OneQuick.UserData["xClipboard_FavourClips"] := xClipboard.FavourClips 1554 | Return 1555 | 1556 | 1557 | 1558 | ; ////////////////////////////////////////////////////////////////////////// 1559 | ; ////////////////////////////////////////////////////////////////////////// 1560 | ; ////////////////////////////////////////////////////////////////////////// 1561 | /* 1562 | config struct: [start_hour, start_min, end_hour, end_min, function_or_label_name [,peroid(seconds) ,weekday(1-7)]] 1563 | e.g. 1564 | Schedule.Add([[0,0,0,0,"func1"], [8,0,20,0,"func2","3600","12345"]]) 1565 | Schedule.Start() 1566 | */ 1567 | class Schedule 1568 | { 1569 | static SchdArr := [] 1570 | 1571 | Start() 1572 | { 1573 | SetTimer, Sub_Schedule, 1000 1574 | } 1575 | 1576 | Stop() 1577 | { 1578 | SetTimer, Sub_Schedule, Off 1579 | } 1580 | 1581 | Add(config) 1582 | { 1583 | Loop, % config.MaxIndex() 1584 | { 1585 | Schedule.SchdArr.Insert(config[A_Index]) 1586 | } 1587 | } 1588 | } 1589 | 1590 | Sub_Schedule: 1591 | Loop % Schedule.SchdArr.MaxIndex() 1592 | { 1593 | schedule_entry := Schedule.SchdArr[A_Index] 1594 | If (schedule_entry.MaxIndex() < 5) 1595 | Continue 1596 | If (schedule_entry.MaxIndex() == 7) && !InStr(schedule_entry[7], mod(A_WDay+5,7)+1) ;A_WDay=1 for Sunday 1597 | Continue 1598 | schedule_t1 := A_Hour > schedule_entry[1] 1599 | || A_Hour = schedule_entry[1] && A_Min >= schedule_entry[2] 1600 | schedule_t2 :=A_Hour < schedule_entry[3] 1601 | || A_Hour = schedule_entry[3] && A_Min <= schedule_entry[4] 1602 | schedule_otherday := schedule_entry[1] > schedule_entry[3] 1603 | || schedule_entry[1] = schedule_entry[3] 1604 | && schedule_entry[2] >= schedule_entry[4] 1605 | if ( !schedule_otherday && (schedule_t1 && schedule_t2) 1606 | || schedule_otherday && (schedule_t1 || schedule_t2) ) 1607 | { 1608 | A_TimeStamp := A_Now 1609 | A_TimeStamp -= 19700101000000,seconds 1610 | if (schedule_entry.MaxIndex() < 6) || !schedule_last_launch_%A_Index% 1611 | || (A_TimeStamp - schedule_last_launch_%A_Index% >= schedule_entry[6]) 1612 | { 1613 | schedule_t_str := schedule_entry[5] 1614 | schedule_last_launch_%A_Index% := A_TimeStamp 1615 | run(schedule_t_str) 1616 | } 1617 | } 1618 | } 1619 | Return 1620 | 1621 | 1622 | 1623 | 1624 | 1625 | 1626 | 1627 | ; ////////////////////////////////////////////////////////////////////////// 1628 | ; ////////////////////////////////////////////////////////////////////////// 1629 | ; ////////////////////////////////////////////////////////////////////////// 1630 | /* 1631 | 1632 | */ 1633 | class WinMenu 1634 | { 1635 | static InfoObj := {} 1636 | static HideIDs := {} 1637 | static ini_registered := 0 1638 | 1639 | Ini() 1640 | { 1641 | if (this.ini_registered == 1) 1642 | Return 1643 | this.HideIDs := OneQuick.UserData["WinMenu_HideIDs"] 1644 | if not IsObject(this.HideIDs) 1645 | this.HideIDs := {} 1646 | OneQuick.OnExit("Sub_WinMenu_OnExit") 1647 | this.ini_registered := 1 1648 | } 1649 | 1650 | Show(ID := "") 1651 | { 1652 | if (ID == "") 1653 | ID := Sys.Win.ID() 1654 | Title := Sys.Win.Title(ID) 1655 | Path := Sys.Win.Path(ID) 1656 | Cls := Sys.Win.Class(ID) 1657 | this.InfoObj[1] := Title 1658 | this.InfoObj[2] := Path 1659 | this.InfoObj[3] := ID 1660 | this.InfoObj[4] := Cls 1661 | Title := SubStr(Title, 1, 150) 1662 | Path := SubStr(Path, 1, 150) 1663 | try 1664 | { 1665 | Menu, windowMenu, DeleteAll 1666 | } 1667 | Try 1668 | { 1669 | Menu, windowMenu_ShowWinMenu, DeleteAll 1670 | } 1671 | Try 1672 | { 1673 | Menu, WinMenu_Trans, DeleteAll 1674 | } 1675 | Menu, windowMenu, Add, % lang("Topmost"), Sub_WinMenu_TopMost 1676 | if Sys.Win.IsTopmost(winID) 1677 | Menu, windowMenu, Check, % lang("Topmost") 1678 | Loop, 9 1679 | { 1680 | Menu, WinMenu_Trans, Add, % (110-A_Index*10)`%, Sub_WinMenu_Trans 1681 | } 1682 | Trans := Sys.Win.Transparent() 1683 | Try 1684 | { 1685 | Menu, WinMenu_Trans, Check, %Trans%`% 1686 | } 1687 | Menu, windowMenu, Add, % lang("Transparent") ": " Trans "`%", :WinMenu_Trans 1688 | Menu, windowMenu, Add, % lang("Open Location"), Sub_WinMenu_ExplorerSelect 1689 | Menu, windowMenu, Add 1690 | Menu, windowMenu, Add, Title: %Title%, Sub_WinMenu_CopyToClipboard 1691 | Menu, windowMenu, Add, Path: %Path%, Sub_WinMenu_CopyToClipboard 1692 | Menu, windowMenu, Add, ID: %ID%, Sub_WinMenu_CopyToClipboard 1693 | Menu, windowMenu, Add, Class: %Cls%, Sub_WinMenu_CopyToClipboard 1694 | Menu, windowMenu, Add 1695 | Menu, windowMenu, Add, Hide Window, Sub_WinMenu_HideWindow 1696 | HideIDs_IsVoid := 1 1697 | For k, v in this.HideIDs 1698 | { 1699 | Menu, windowMenu_ShowWinMenu, Add, % k, Sub_WinMenu_ShowWindow 1700 | HideIDs_IsVoid := 0 1701 | } 1702 | if (HideIDs_IsVoid) 1703 | { 1704 | Menu, windowMenu_ShowWinMenu, Add, , Sub_WinMenu_ShowWindow 1705 | Menu, windowMenu_ShowWinMenu, Disable, 1706 | } 1707 | Menu, windowMenu, Add, Show Window, :windowMenu_ShowWinMenu 1708 | Menu, windowMenu, Show 1709 | } 1710 | } 1711 | 1712 | Sub_WinMenu_TopMost: 1713 | Sys.Win.Topmost(WinMenu.InfoObj[3]) 1714 | Return 1715 | 1716 | Sub_WinMenu_Trans: 1717 | Sys.Win.Transparent(ceil(110-A_ThisMenuItemPos*10)) 1718 | Return 1719 | 1720 | Sub_WinMenu_ExplorerSelect: 1721 | Sys.Win.ExplorerSelect(WinMenu.InfoObj[2]) 1722 | Return 1723 | 1724 | Sub_WinMenu_CopyToClipboard: 1725 | xClipboard.ShowClipMenu(WinMenu.InfoObj[A_ThisMenuItemPos - 4]) 1726 | Return 1727 | 1728 | Sub_WinMenu_HideWindow: 1729 | id := WinMenu.InfoObj[3] 1730 | WinHide, ahk_id %id% 1731 | WinMenu.HideIDs[id " " WinMenu.InfoObj[1]] := id 1732 | Return 1733 | 1734 | Sub_WinMenu_ShowWindow: 1735 | id := WinMenu.HideIDs[A_ThisMenuItem] 1736 | Sys.Win.Show(id) 1737 | WinMenu.HideIDs.Remove(A_ThisMenuItem) 1738 | Return 1739 | 1740 | Sub_WinMenu_OnExit: 1741 | OneQuick.UserData["WinMenu_HideIDs"] := WinMenu.HideIDs 1742 | Return 1743 | 1744 | 1745 | ; ////////////////////////////////////////////////////////////////////////// 1746 | ; ////////////////////////////////////////////////////////////////////////// 1747 | ; ////////////////////////////////////////////////////////////////////////// 1748 | /* 1749 | e.g. 1750 | xMenu.Add("Menu1", [["item1","func1"],["item2","func2"],[] 1751 | ,["submenu",["subitem_1","func3"] 1752 | ,["subitem_2",, {sub: "SubMenu", "disable"}]]]) 1753 | xMenu.Show("Menu1") 1754 | */ 1755 | class xMenu 1756 | { 1757 | static MenuList := {} 1758 | 1759 | Show(Menu_Name, X := "", Y := "") 1760 | { 1761 | if (X == "" || Y == "") 1762 | Menu, %Menu_Name%, Show 1763 | Else 1764 | Menu, %Menu_Name%, Show, % X, % Y 1765 | } 1766 | 1767 | New(Menu_Name, Menu_Config) 1768 | { 1769 | this.Clear(Menu_Name) 1770 | this.Add(Menu_Name, Menu_Config) 1771 | } 1772 | 1773 | Clear(Menu_Name) 1774 | { 1775 | Try 1776 | { 1777 | Menu, %Menu_Name%, DeleteAll 1778 | } 1779 | } 1780 | 1781 | Add(Menu_Name, Menu_Config) 1782 | { 1783 | ParsedCfg := this._Config_Parse(Menu_Name, Menu_Config) 1784 | Loop, % ParsedCfg.MaxIndex() 1785 | { 1786 | cfg_entry := ParsedCfg[A_Index] 1787 | if (cfg_entry[4].HasKey("sub")) 1788 | { 1789 | sub_name := cfg_entry[4]["sub"] 1790 | Menu, % cfg_entry[1], Add, % cfg_entry[2], :%sub_name% 1791 | } 1792 | Else 1793 | { 1794 | Menu, % cfg_entry[1], Add, % cfg_entry[2], Sub_xMenu_Open 1795 | this.MenuList[cfg_entry[1] "_" cfg_entry[2]] := cfg_entry[3] 1796 | } 1797 | For Key, Value in cfg_entry[4] 1798 | { 1799 | if Value = 0 1800 | Continue 1801 | StringLower, Key, Key 1802 | if(Key == "check") 1803 | Menu, % cfg_entry[1], Check, % cfg_entry[2] 1804 | if(Key == "uncheck") 1805 | Menu, % cfg_entry[1], UnCheck, % cfg_entry[2] 1806 | if(Key == "togglecheck") 1807 | Menu, % cfg_entry[1], ToggleCheck, % cfg_entry[2] 1808 | if(Key == "enable") 1809 | Menu, % cfg_entry[1], Enable, % cfg_entry[2] 1810 | if(Key == "disable") 1811 | Menu, % cfg_entry[1], Disable, % cfg_entry[2] 1812 | if(Key == "toggleenable") 1813 | Menu, % cfg_entry[1], ToggleEnable, % cfg_entry[2] 1814 | } 1815 | } 1816 | } 1817 | 1818 | _Config_Parse(PName, Config) 1819 | { 1820 | ParsedCfg := {} 1821 | Loop, % Config.MaxIndex() 1822 | { 1823 | cfg_entry := Config[A_Index] 1824 | If IsObject(cfg_entry[2]) 1825 | { 1826 | ParsedCfg_Sub := this._Config_Parse(cfg_entry[1], cfg_entry[2]) 1827 | Loop, % ParsedCfg_Sub.MaxIndex() 1828 | { 1829 | sub_entry := ParsedCfg_Sub[A_Index] 1830 | ParsedCfg.Insert([sub_entry[1],sub_entry[2],sub_entry[3],sub_entry[4]]) 1831 | } 1832 | ParsedCfg.Insert([PName,cfg_entry[1],,{"sub":cfg_entry[1]}]) 1833 | } 1834 | Else 1835 | { 1836 | if cfg_entry.MaxIndex() == 3 1837 | cfg_ctrl := cfg_entry[3] 1838 | Else 1839 | cfg_ctrl := {} 1840 | ParsedCfg.Insert([PName,cfg_entry[1],cfg_entry[2],cfg_ctrl]) 1841 | } 1842 | } 1843 | Return % ParsedCfg 1844 | } 1845 | } 1846 | 1847 | Sub_xMenu_Open: 1848 | Run(xMenu.MenuList[A_ThisMenu "_" A_ThisMenuItem]) 1849 | Return 1850 | 1851 | 1852 | 1853 | 1854 | 1855 | ; ////////////////////////////////////////////////////////////////////////// 1856 | ; ////////////////////////////////////////////////////////////////////////// 1857 | ; ////////////////////////////////////////////////////////////////////////// 1858 | /* 1859 | 1860 | */ 1861 | class Sys 1862 | { 1863 | class Power 1864 | { 1865 | MonitorOff() 1866 | { 1867 | SendMessage, 0x112, 0xF170, 2,, Program Manager 1868 | } 1869 | 1870 | Lock() 1871 | { 1872 | run("Rundll32.exe User32.dll,LockWorkStation") 1873 | } 1874 | 1875 | LockAndMonitoroff() 1876 | { 1877 | this.Lock() 1878 | sleep 1500 1879 | this.MonitorOff() 1880 | } 1881 | 1882 | Standby() 1883 | { 1884 | /* 1885 | if you want to use this function, you can download psshutdown.exe from 1886 | https://technet.microsoft.com/en-us/sysinternals/psshutdown.aspx 1887 | then put psshutdown.exe in tool/ folder 1888 | */ 1889 | if FileExist("tool/psshutdown.exe") 1890 | { 1891 | run % "tool/psshutdown.exe -d -t 0" 1892 | } 1893 | Else 1894 | { 1895 | m("can't find psshutdown.exe, you can download it yourself and put it in tool/ folder.") 1896 | run("https://technet.microsoft.com/en-us/sysinternals/psshutdown.aspx") 1897 | } 1898 | } 1899 | 1900 | Shutdown(countdown := 0) 1901 | { 1902 | run shutdown /s /f /t %countdown% 1903 | } 1904 | 1905 | Restart() 1906 | { 1907 | run shutdown /r /f 1908 | } 1909 | 1910 | BatteryIsCharging() 1911 | { 1912 | VarSetCapacity(powerstatus, 1+1+1+1+4+4) 1913 | success := DllCall("kernel32.dll\GetSystemPowerStatus", "uint", &powerstatus) 1914 | 1915 | acLineStatus := this._ReadInteger(&powerstatus,0,1,false) 1916 | 1917 | return % acLineStatus 1918 | } 1919 | 1920 | BatteryPercent() 1921 | { 1922 | VarSetCapacity(powerstatus, 1+1+1+1+4+4) 1923 | success := DllCall("kernel32.dll\GetSystemPowerStatus", "uint", &powerstatus) 1924 | 1925 | ;batteryFlag:=this._ReadInteger(&powerstatus,1,1,false) 1926 | batteryLifePercent := this._ReadInteger(&powerstatus,2,1,false) 1927 | ;batteryLifeTime:=this._ReadInteger(&powerstatus,4,4,false) 1928 | ;batteryFullLifeTime:=this._ReadInteger(&powerstatus,8,4,false) 1929 | 1930 | return % batteryLifePercent 1931 | } 1932 | 1933 | _ReadInteger( p_address, p_offset, p_size, p_hex=true ) 1934 | { 1935 | value = 0 1936 | old_FormatInteger := a_FormatInteger 1937 | if ( p_hex ) 1938 | SetFormat, integer, hex 1939 | else 1940 | SetFormat, integer, dec 1941 | loop, %p_size% 1942 | value := value+( *( ( p_address+p_offset )+( a_Index-1 ) ) << ( 8* ( a_Index-1 ) ) ) 1943 | SetFormat, integer, %old_FormatInteger% 1944 | return, value 1945 | } 1946 | 1947 | } 1948 | 1949 | class Screen 1950 | { 1951 | Off() 1952 | { 1953 | SendMessage, 0x112, 0xF170, 2,, Program Manager 1954 | } 1955 | 1956 | _find_display_exe() 1957 | { 1958 | if(FileExist("tool/display.exe")) 1959 | { 1960 | return True 1961 | } 1962 | Else 1963 | { 1964 | m("can't find display.exe, you can download it yourself and put it in tool/ folder.") 1965 | run("http://noeld.com/programs.asp#Display") 1966 | } 1967 | } 1968 | 1969 | RotateTo(angle) 1970 | { 1971 | if (angle != "0" && angle != "90" 1972 | && angle != "180" && angle != "270") 1973 | Throw, angle must be 0, 90, 180, or 270 1974 | if(this._find_display_exe()) 1975 | { 1976 | Run, tool/display.exe /rotate %angle%,,Hide 1977 | } 1978 | } 1979 | 1980 | RotateCW() 1981 | { 1982 | if(this._find_display_exe()) 1983 | { 1984 | Run, tool/display.exe /rotate cw,,Hide 1985 | } 1986 | } 1987 | 1988 | RotateCCW() 1989 | { 1990 | if(this._find_display_exe()) 1991 | { 1992 | Run, tool/display.exe /rotate ccw,,Hide 1993 | } 1994 | } 1995 | 1996 | BrightnessUp() { 1997 | this.Brightness(+2) 1998 | } 1999 | BrightnessDown() { 2000 | this.Brightness(-2) 2001 | } 2002 | 2003 | ; http://www.autohotkey.com/board/topic/83100-laptop-screen-brightness/ 2004 | Brightness(IndexMove) 2005 | { 2006 | VarSetCapacity(SupportedBrightness, 256, 0) 2007 | VarSetCapacity(SupportedBrightnessSize, 4, 0) 2008 | VarSetCapacity(BrightnessSize, 4, 0) 2009 | VarSetCapacity(Brightness, 3, 0) 2010 | 2011 | hLCD := DllCall("CreateFile" 2012 | , Str, "\\.\LCD" 2013 | , UInt, 0x80000000 | 0x40000000 ;Read | Write 2014 | , UInt, 0x1 | 0x2 ; File Read | File Write 2015 | , UInt, 0 2016 | , UInt, 0x3 ; open any existing file 2017 | , UInt, 0 2018 | , UInt, 0) 2019 | 2020 | if hLCD != -1 2021 | { 2022 | 2023 | DevVideo := 0x00000023, BuffMethod := 0, Fileacces := 0 2024 | NumPut(0x03, Brightness, 0, "UChar") ; 0x01 = Set AC, 0x02 = Set DC, 0x03 = Set both 2025 | NumPut(0x00, Brightness, 1, "UChar") ; The AC brightness level 2026 | NumPut(0x00, Brightness, 2, "UChar") ; The DC brightness level 2027 | DllCall("DeviceIoControl" 2028 | , UInt, hLCD 2029 | , UInt, (DevVideo<<16 | 0x126<<2 | BuffMethod<<14 | Fileacces) ; IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS 2030 | , UInt, 0 2031 | , UInt, 0 2032 | , UInt, &Brightness 2033 | , UInt, 3 2034 | , UInt, &BrightnessSize 2035 | , UInt, 0) 2036 | 2037 | DllCall("DeviceIoControl" 2038 | , UInt, hLCD 2039 | , UInt, (DevVideo<<16 | 0x125<<2 | BuffMethod<<14 | Fileacces) ; IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS 2040 | , UInt, 0 2041 | , UInt, 0 2042 | , UInt, &SupportedBrightness 2043 | , UInt, 256 2044 | , UInt, &SupportedBrightnessSize 2045 | , UInt, 0) 2046 | 2047 | ACBrightness := NumGet(Brightness, 1, "UChar") 2048 | ACIndex := 0 2049 | DCBrightness := NumGet(Brightness, 2, "UChar") 2050 | DCIndex := 0 2051 | BufferSize := NumGet(SupportedBrightnessSize, 0, "UInt") 2052 | MaxIndex := BufferSize-1 2053 | 2054 | Loop, %BufferSize% 2055 | { 2056 | ThisIndex := A_Index-1 2057 | ThisBrightness := NumGet(SupportedBrightness, ThisIndex, "UChar") 2058 | if ACBrightness = %ThisBrightness% 2059 | ACIndex := ThisIndex 2060 | if DCBrightness = %ThisBrightness% 2061 | DCIndex := ThisIndex 2062 | } 2063 | 2064 | if DCIndex >= %ACIndex% 2065 | BrightnessIndex := DCIndex 2066 | else 2067 | BrightnessIndex := ACIndex 2068 | 2069 | BrightnessIndex += IndexMove 2070 | 2071 | if BrightnessIndex > %MaxIndex% 2072 | BrightnessIndex := MaxIndex 2073 | 2074 | if BrightnessIndex < 0 2075 | BrightnessIndex := 0 2076 | 2077 | NewBrightness := NumGet(SupportedBrightness, BrightnessIndex, "UChar") 2078 | 2079 | NumPut(0x03, Brightness, 0, "UChar") ; 0x01 = Set AC, 0x02 = Set DC, 0x03 = Set both 2080 | NumPut(NewBrightness, Brightness, 1, "UChar") ; The AC brightness level 2081 | NumPut(NewBrightness, Brightness, 2, "UChar") ; The DC brightness level 2082 | 2083 | DllCall("DeviceIoControl" 2084 | , UInt, hLCD 2085 | , UInt, (DevVideo<<16 | 0x127<<2 | BuffMethod<<14 | Fileacces) ; IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS 2086 | , UInt, &Brightness 2087 | , UInt, 3 2088 | , UInt, 0 2089 | , UInt, 0 2090 | , UInt, 0 2091 | , Uint, 0) 2092 | 2093 | DllCall("CloseHandle", UInt, hLCD) 2094 | } 2095 | } 2096 | 2097 | } 2098 | 2099 | class Network 2100 | { 2101 | EditHOSTS() 2102 | { 2103 | hosts = %SystemRoot%\system32\drivers\etc\hosts 2104 | OneQuick.Edit(hosts, 1) 2105 | run ipconfig /flushdns 2106 | } 2107 | 2108 | SetWifiAP(ssid, pw) 2109 | { 2110 | run *RunAs cmd.exe /c netsh wlan set hostednetwork mode=allow ssid=%ssid% key=%pw% 2111 | } 2112 | 2113 | OpenWifiAP() 2114 | { 2115 | Run *RunAs cmd.exe /c netsh wlan start hostednetwork 2116 | } 2117 | 2118 | CloseWifiAP() 2119 | { 2120 | run netsh wlan stop hostednetwork 2121 | } 2122 | } 2123 | 2124 | class Volume 2125 | { 2126 | static Volume_Interval := 2 2127 | 2128 | Get() 2129 | { 2130 | SoundGet, volume 2131 | return % round(volume, 1) 2132 | } 2133 | 2134 | Set(vol) 2135 | { 2136 | if ( vol <= 0 ) 2137 | vol := 0.005 2138 | SoundSet, % vol 2139 | return % round(vol, 1) 2140 | } 2141 | 2142 | Up() 2143 | { 2144 | return % this.Set(this.Get() + this.Volume_Interval) 2145 | } 2146 | 2147 | Down() 2148 | { 2149 | return % this.Set(this.Get() - this.Volume_Interval) 2150 | } 2151 | 2152 | IsMute() 2153 | { 2154 | SoundGet, master_mute, , mute 2155 | return % master_mute = "on" 2156 | } 2157 | 2158 | SetMute() 2159 | { 2160 | SoundSet, 1,, Mute 2161 | } 2162 | 2163 | UnsetMute() 2164 | { 2165 | SoundSet, 0,, Mute 2166 | } 2167 | } 2168 | 2169 | class Cursor 2170 | { 2171 | static CornerPixel := 8 2172 | static info_switch := 0 2173 | 2174 | CornerPos(X := "", Y := "", cornerPix = "") 2175 | { 2176 | if (X = "") or (Y = "") 2177 | { 2178 | MouseGetPos, X, Y 2179 | } 2180 | if(cornerPix = "") 2181 | { 2182 | cornerPix := this.CornerPixel 2183 | } 2184 | ; Multi Monitor Support 2185 | SysGet, MonitorCount, MonitorCount 2186 | Loop, % MonitorCount 2187 | { 2188 | SysGet, Mon, Monitor, % A_Index 2189 | if(X>=MonLeft && Y>= MonTop && X= MonRight - cornerPix) 2195 | str .= "R" 2196 | if ( Y < MonTop + cornerPix ) 2197 | str .= "T" 2198 | else if ( Y >= MonBottom - cornerPix) 2199 | str .= "B" 2200 | return % str 2201 | } 2202 | } 2203 | return "" 2204 | } 2205 | 2206 | IsPos(pos, cornerPix = "") 2207 | { 2208 | StringUpper, pos, pos 2209 | pos_now := this.CornerPos("", "", cornerPix) 2210 | if (pos_now == "") && (pos == "") 2211 | Return 2212 | if StrLen(pos_now) == 1 2213 | Return % (pos_now == pos) 2214 | Else 2215 | pos_now2 := SubStr(pos_now,2,1) SubStr(pos_now,1,1) 2216 | Return ((pos_now == pos) || (pos_now2 == pos)) 2217 | } 2218 | 2219 | Info() 2220 | { 2221 | this.info_switch := !this.info_switch 2222 | if (this.info_switch) 2223 | { 2224 | Gosub, Sub_Sys_Cursor_Info 2225 | Settimer, Sub_Sys_Cursor_Info, 500 2226 | } 2227 | } 2228 | } 2229 | 2230 | ; Sys.Win 2231 | class Win 2232 | { 2233 | ID() 2234 | { 2235 | WinGet, winID, ID, A 2236 | return % winID 2237 | } 2238 | 2239 | Title(winID := "") 2240 | { 2241 | if (winID == "") 2242 | winID := this.ID() 2243 | WinGetTitle, title, ahk_id %winID% 2244 | return % title 2245 | } 2246 | 2247 | Class(winID := "") 2248 | { 2249 | if (winID == "") 2250 | winID := this.ID() 2251 | WinGetClass, class, ahk_id %winID% 2252 | return % class 2253 | } 2254 | 2255 | GetParent(winID := "") 2256 | { 2257 | if (winID == "") 2258 | winID := this.ID() 2259 | while (winID != 0) 2260 | { 2261 | lastID := winID 2262 | winID := DllCall("GetParent", UInt, winID) 2263 | } 2264 | return lastID 2265 | } 2266 | 2267 | Path(winID := "") 2268 | { 2269 | if (winID == "") 2270 | winID := this.ID() 2271 | WinGet, path, ProcessPath, ahk_id %winID% 2272 | return % path 2273 | } 2274 | 2275 | ExplorerSelect(path) 2276 | { 2277 | run("explorer /select," path) 2278 | } 2279 | 2280 | IsRunning(class) 2281 | { 2282 | DetectHiddenWindows, On ; 可检测到被hide的窗口 2283 | re := winexist(class) 2284 | DetectHiddenWindows, off 2285 | return %re% 2286 | } 2287 | 2288 | IsFullScreen(winID := "") 2289 | { 2290 | ;checks if the specified window is full screen 2291 | ;code from NiftyWindows source 2292 | ;(with only slight modification) 2293 | 2294 | ;use WinExist of another means to get the Unique ID (HWND) of the desired window 2295 | 2296 | if (winID == "") 2297 | winID := this.ID() 2298 | 2299 | WinGet, WinMinMax, MinMax, ahk_id %WinID% 2300 | WinGetPos, WinX, WinY, WinW, WinH, ahk_id %WinID% 2301 | 2302 | if (WinMinMax = 0) && (WinX = 0) && (WinY = 0) && (WinW = A_ScreenWidth) && (WinH = A_ScreenHeight) 2303 | { 2304 | WinGetClass, WinClass, ahk_id %WinID% 2305 | WinGet, WinProcessName, ProcessName, ahk_id %WinID% 2306 | SplitPath, WinProcessName, , , WinProcessExt 2307 | 2308 | if (WinClass != "Progman") and (WinClass != "WorkerW") and (WinProcessExt != "scr") 2309 | { 2310 | ;program is full-screen 2311 | return 1 2312 | } 2313 | } 2314 | 2315 | return 0 2316 | 2317 | } 2318 | 2319 | IsTopmost(winID = "") 2320 | { 2321 | if (winID == "") 2322 | winID := this.ID() 2323 | WinGet, ExStyle, ExStyle, ahk_id %winID% 2324 | if (ExStyle & 0x8) ; 0x8 is WS_EX_TOPMOST. 2325 | return true 2326 | else 2327 | return false 2328 | } 2329 | 2330 | Topmost(winID := "", top := "") 2331 | { 2332 | if (winID == "") 2333 | winID := this.ID() 2334 | if (top = "") 2335 | top := not this.IsTopmost(winID) 2336 | if top 2337 | { 2338 | WinSet, AlwaysOnTop, on, ahk_id %winID% 2339 | } 2340 | else 2341 | { 2342 | Winset, AlwaysOnTop, off, ahk_id %winID% 2343 | } 2344 | } 2345 | 2346 | Transparent(moveto := "", winID := "") 2347 | { 2348 | if (winID == "") 2349 | winID := this.ID() 2350 | WinGet, Transparent, Transparent, ahk_id %winID% 2351 | If (Transparent = "") 2352 | Transparent = 255 2353 | if (moveto = "") 2354 | Return % floor(Transparent/2.55) 2355 | Transparent_New := moveto * 2.55 2356 | If (Transparent_New < 51) 2357 | Transparent_New = 51 2358 | If (Transparent_New > 254 ) 2359 | Transparent_New = 255 2360 | WinSet, Transparent, %Transparent_New%, ahk_id %winID% 2361 | } 2362 | 2363 | Show(winID := "") 2364 | { 2365 | if (winID == "") 2366 | winID := this.ID() 2367 | WinShow, ahk_id %winID% 2368 | } 2369 | 2370 | Hide(winID := "") 2371 | { 2372 | if (winID == "") 2373 | winID := this.ID() 2374 | WinHide, ahk_id %winID% 2375 | } 2376 | 2377 | DisableCloseButton(hWnd="") 2378 | { 2379 | If hWnd= 2380 | hWnd:=WinExist("A") 2381 | hSysMenu:=DllCall("GetSystemMenu","Int",hWnd,"Int",FALSE) 2382 | nCnt:=DllCall("GetMenuItemCount","Int",hSysMenu) 2383 | DllCall("RemoveMenu","Int",hSysMenu,"UInt",nCnt-1,"Uint","0x400") 2384 | DllCall("RemoveMenu","Int",hSysMenu,"UInt",nCnt-2,"Uint","0x400") 2385 | DllCall("DrawMenuBar","Int",hWnd) 2386 | } 2387 | 2388 | GotoPreApp() 2389 | { 2390 | send !+{esc} 2391 | winget, x ,MinMax, A 2392 | if x=-1 2393 | WinRestore A 2394 | } 2395 | 2396 | GotoNextApp() 2397 | { 2398 | send !{esc} 2399 | winget, x ,MinMax, A 2400 | if x=-1 2401 | WinRestore A 2402 | } 2403 | 2404 | ; Sys.Win.GotoPreTab 2405 | GotoPreTab() 2406 | { 2407 | if(Sys.Win.Class()="PX_WINDOW_CLASS") { 2408 | send ^{PgUp} 2409 | } 2410 | else { 2411 | send ^+{tab} 2412 | } 2413 | } 2414 | 2415 | ; Sys.Win.GotoNextTab 2416 | GotoNextTab() 2417 | { 2418 | if(Sys.Win.Class()="PX_WINDOW_CLASS") { 2419 | send ^{PgDn} 2420 | } 2421 | else { 2422 | send ^{tab} 2423 | } 2424 | } 2425 | } 2426 | 2427 | BitLocker_Relock(char_Drive) 2428 | { 2429 | Run *RunAs cmd.exe /c manage-bde -lock %char_Drive%: 2430 | } 2431 | 2432 | } 2433 | 2434 | Sub_Sys_Cursor_Info: 2435 | ; if write these close code to info() function and use a menu to close, tooltip will not destroyed 2436 | if (!Sys.Cursor.info_switch) 2437 | { 2438 | ToolTip,,,, 9 2439 | SetTimer, Sub_Sys_Cursor_Info, Off 2440 | Return 2441 | } 2442 | MouseGetPos, X, Y 2443 | PixelGetColor, color, %X%, %Y%, RGB 2444 | VarSetCapacity(Point, 8, 0) 2445 | DllCall("GetCursorPos", ptr, &Point) 2446 | hwnd := DllCall("WindowFromPoint", "int64", NumGet(Point, 0, "int64")) 2447 | WinGetClass, mcls, ahk_id %hwnd% 2448 | Sys_Cursor_Info_Text := "" 2449 | . "Pos: " . "X " . X . " , Y " . Y . "`r`n" 2450 | . "Color: " . color . "`r`n" 2451 | . "hwnd: " . hwnd . "`r`n" 2452 | . "Class: " . mcls . "`r`n" 2453 | . "--------------------`r`n" 2454 | . "F1,F2 Calculate position`r`n" 2455 | . "F4 Copy to clipboard`r`n" 2456 | . "ESC Close Info`r`n" 2457 | ToolTip, % Sys_Cursor_Info_Text,,, 9 2458 | Return 2459 | 2460 | #if Sys.Cursor.info_switch 2461 | f1:: 2462 | MouseGetPos, Sys_Cursor_Info_rem_x, Sys_Cursor_Info_rem_y 2463 | m("move mouse and press F2") 2464 | return 2465 | 2466 | f2:: 2467 | CoordMode, Mouse, Screen ;设置绝对坐标 2468 | MouseGetPos, x, y 2469 | m("X" abs(Sys_Cursor_Info_rem_x-x) " Y" abs(Sys_Cursor_Info_rem_y-y)) 2470 | return 2471 | 2472 | f4:: 2473 | clipboard := Sys_Cursor_Info_Text 2474 | m("Copy to Clipboard") 2475 | return 2476 | 2477 | esc:: 2478 | Sys.Cursor.Info() 2479 | return 2480 | #if 2481 | 2482 | ; ////////////////////////////////////////////////////////////////////////// 2483 | ; ////////////////////////////////////////////////////////////////////////// 2484 | ; ////////////////////////////////////////////////////////////////////////// 2485 | /* 2486 | 2487 | */ 2488 | class DateTime 2489 | { 2490 | SecondsToStr(NumberOfSeconds) 2491 | { 2492 | time = 19990101 ; *Midnight* of an arbitrary date. 2493 | time += %NumberOfSeconds%, seconds 2494 | FormatTime, mmss, %time%, mm:ss 2495 | return NumberOfSeconds//3600 ":" mmss ; This method is used to support more than 24 hours worth of sections. 2496 | } 2497 | 2498 | TimeStamp(YYYYMMDDHH24MISS := "") 2499 | { 2500 | if !YYYYMMDDHH24MISS 2501 | A_TimeStamp := A_Now 2502 | Else 2503 | A_TimeStamp := YYYYMMDDHH24MISS 2504 | A_TimeStamp -= 19700101000000,seconds 2505 | Return % A_TimeStamp 2506 | } 2507 | } 2508 | 2509 | CountObj(obj) 2510 | { 2511 | count := 0 2512 | For Key, val in obj 2513 | { 2514 | count := count + 1 2515 | } 2516 | return % count 2517 | } 2518 | 2519 | /* 2520 | * http://www.autohotkey.com/forum/viewtopic.php?t=71619 2521 | */ 2522 | UriEncode(Uri, Enc = "UTF-8") 2523 | { 2524 | StrPutVar(Uri, Var, Enc) 2525 | f := A_FormatInteger 2526 | SetFormat, IntegerFast, H 2527 | Loop 2528 | { 2529 | Code := NumGet(Var, A_Index - 1, "UChar") 2530 | If (!Code) 2531 | Break 2532 | If (Code >= 0x30 && Code <= 0x39 ; 0-9 2533 | || Code >= 0x41 && Code <= 0x5A ; A-Z 2534 | || Code >= 0x61 && Code <= 0x7A) ; a-z 2535 | Res .= Chr(Code) 2536 | Else 2537 | Res .= "%" . SubStr(Code + 0x100, -1) 2538 | } 2539 | SetFormat, IntegerFast, %f% 2540 | Return, Res 2541 | } 2542 | 2543 | UriDecode(Uri, Enc = "UTF-8") 2544 | { 2545 | Pos := 1 2546 | Loop 2547 | { 2548 | Pos := RegExMatch(Uri, "i)(?:%[\da-f]{2})+", Code, Pos++) 2549 | If (Pos = 0) 2550 | Break 2551 | VarSetCapacity(Var, StrLen(Code) // 3, 0) 2552 | StringTrimLeft, Code, Code, 1 2553 | Loop, Parse, Code, `% 2554 | NumPut("0x" . A_LoopField, Var, A_Index - 1, "UChar") 2555 | StringReplace, Uri, Uri, `%%Code%, % StrGet(&Var, Enc), All 2556 | } 2557 | Return, Uri 2558 | } 2559 | 2560 | StrPutVar(Str, ByRef Var, Enc = "") 2561 | { 2562 | Len := StrPut(Str, Enc) * (Enc = "UTF-16" || Enc = "CP1200" ? 2 : 1) 2563 | VarSetCapacity(Var, Len, 0) 2564 | Return, StrPut(Str, &Var, Enc) 2565 | } 2566 | 2567 | ; /////////////////////////////////////////////////////////////////////////// 2568 | d(str := "") 2569 | { 2570 | if(OneQuick._DEBUG_) 2571 | { 2572 | m("[DEBUG]: " str) 2573 | } 2574 | } 2575 | 2576 | m(str := "") 2577 | { 2578 | if(IsObject(str)) { 2579 | str := "[Object]`n" Yaml_dump(str) 2580 | } 2581 | MsgBox, , % OneQuick.ProgramName, % str 2582 | } 2583 | 2584 | mq(msg:="", opt:=0x1024, title:="") 2585 | { 2586 | title := title="" ? OneQuick.ProgramName : title 2587 | MsgBox, % opt, % title, % msg 2588 | IfMsgBox YES 2589 | return True 2590 | return False 2591 | } 2592 | 2593 | t(str := "") 2594 | { 2595 | if (str != "") 2596 | ToolTip, % str 2597 | Else 2598 | ToolTip 2599 | } 2600 | 2601 | RunArr(arr) 2602 | { 2603 | Loop, % arr.MaxIndex() 2604 | { 2605 | run(arr[A_Index]) 2606 | } 2607 | } 2608 | 2609 | ; 万能的run 函数 2610 | ; 参数可以是cmd命令,代码中的sub,function,网址,b站av号,还可以扩展 2611 | run(command, throwErr := 1) 2612 | { 2613 | if(IsLabel(command)) 2614 | { 2615 | Gosub, %command% 2616 | } 2617 | else if (IsFunc(command)) 2618 | { 2619 | Array := StrSplit(command, ".") 2620 | If (Array.MaxIndex() >= 2) 2621 | { 2622 | cls := Array[1] 2623 | cls := %cls% 2624 | Loop, % Array.MaxIndex() - 2 2625 | { 2626 | cls := cls[Array[A_Index+1]] 2627 | } 2628 | return cls[Array[Array.MaxIndex()]]() 2629 | } 2630 | Else 2631 | { 2632 | return %command%() 2633 | } 2634 | } 2635 | Else 2636 | { 2637 | if(RegExMatch(command, "^https?://")) 2638 | { 2639 | brw := OneQuick.Browser 2640 | if(brw=""||brw="default") 2641 | run, %command% 2642 | Else if(brw == "microsoft-edge:") 2643 | run, %brw%%command% 2644 | Else 2645 | run, %brw% %command% 2646 | Return 2647 | } 2648 | else if(RegExMatch(command, "i)av(\d+)", avn)) 2649 | { 2650 | run("http://www.bilibili.com/video/av" avn1) 2651 | return 2652 | } 2653 | else if(RegExMatch(command, "i)send (.*)", sd)) 2654 | { 2655 | send, % sd1 2656 | return 2657 | } 2658 | else if(RegExMatch(command, "i)m:(.*)", msg)) 2659 | { 2660 | m(msg1) 2661 | return 2662 | } 2663 | else if(RegExMatch(command, "i)edit:\s*(.*)", f)) 2664 | { 2665 | OneQuick.Edit(f1) 2666 | return 2667 | } 2668 | Try 2669 | { 2670 | run, %command% 2671 | Return 2672 | } 2673 | Catch 2674 | { 2675 | if(IsFunc("run_user")) 2676 | { 2677 | func_name = run_user 2678 | %func_name%(command) 2679 | } 2680 | else if (throwErr == 1) 2681 | MsgBox, 0x30, % OneQuick.ProgramName, % "Can't run command """ command """" 2682 | } 2683 | } 2684 | } 2685 | ; ////////////////////////////////////////////////////////////////////////// 2686 | SUB_ONEQUICK_FILE_END_LABEL: -------------------------------------------------------------------------------- /script/OneQuick.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | @author: XJK 3 | @github: https://github.com/XUJINKAI 4 | 5 | OneQuick starts here, features config file 6 | OneQuick 配置、运行文件 7 | */ 8 | 9 | ; the following lines is necessary to initialize OneQuick class 10 | #SingleInstance force 11 | ; set workdir always be ../ 12 | SplitPath, A_ScriptDir, , workdir 13 | SetWorkingDir, %workdir% 14 | ; include core file 15 | #Include, %A_ScriptDir% 16 | #Include, OneQuick.Core.ahk 17 | OneQuick.Ini() 18 | ; 记录快捷键与对应操作 19 | HOTKEY_REGISTER_LIST := {} 20 | /* 21 | 以下为剪贴板增强功能的定义 22 | 定义了ctrl + shift + x/c/v 三个快捷键 23 | 24 | xClipboard class is a useful Clipboard enhance class, 25 | it provides history list, quick search list, favourite list, etc.. 26 | 27 | xClipboard.SetHotkey(HistoryList, CopyAndShowList, CurrentList) 28 | sets three hotkeys, in this case: 29 | ** ctrl + shift + x open a history list 30 | ** ctrl + shift + c do a copy action first and then shows a search list 31 | ** ctrl + shift + v show search list for current clipboard content without copy action 32 | 33 | xClipboard.SetSearchList([[key, name, website],[...]]) 34 | sets search list, %s in each string will be replaced by the content 35 | */ 36 | if(OneQuick.GetFeatureCfg("clipboard.switch", 0)) 37 | { 38 | ; 快捷键设置 39 | ; xClipboard.SetHotkey("^+x", "^+c", "^+v") 40 | For key, value in OneQuick.GetFeatureCfg("clipboard.hotkey", {}) 41 | register_hotkey(key, value, "") 42 | ; 浏览器 43 | xClipboard_browser := OneQuick.GetFeatureCfg("clipboard.browser", "Default") 44 | xClipboard_browser_list := OneQuick.GetFeatureCfg("clipboard.browser_list", {}) 45 | xClipboard_browser_obj := [] 46 | browser_arr := StrSplit(xClipboard_browser, ",", " ") 47 | Loop, % browser_arr.MaxIndex() 48 | { 49 | key := browser_arr[A_Index] 50 | val := xClipboard_browser_list[key] 51 | xClipboard_browser_obj.push([A_Index, key, val]) 52 | } 53 | xClipboard.SetBrowserList(xClipboard_browser_obj) 54 | ; 快速搜索列表 55 | xClipboard_search := OneQuick.GetFeatureCfg("clipboard.search", "Google") 56 | xClipboard_search_list := OneQuick.GetFeatureCfg("clipboard.search_list", {}) 57 | xClipboard_search_obj := [] 58 | search_arr := StrSplit(xClipboard_search, ",", " ") 59 | Loop, % search_arr.MaxIndex() 60 | { 61 | str := search_arr[A_Index] 62 | str_arr := StrSplit(str, "/") 63 | key := str_arr[1] 64 | hk := str_arr[2] 65 | name := str_arr[3] 66 | if(name="") { 67 | name := key 68 | } 69 | val := xClipboard_search_list[key] 70 | xClipboard_search_obj.push([hk, name, val]) 71 | } 72 | xClipboard.SetSearchList(xClipboard_search_obj) 73 | } 74 | 75 | /* 76 | 以下为超级菜单的自定义代码 77 | 由xMenu模块可以方便地注册自定义菜单 78 | 并由xMenu.Show()函数显示出来 79 | 80 | xMenu class can help register menus 81 | 82 | xMenu.Add(MenuName, [[itemName, Action],[...]]) 83 | Action can be a label name, function name, even a submenu object, or any command runs in system cmd 84 | you can read the comments above run() function in OneQuick.Core.ahk for more information 85 | 86 | after you register a menu, you can use 87 | ---- xMenu.Show(MenuName) ---- 88 | to show the menu you registered 89 | */ 90 | xMenu.Add("System" 91 | ,[["Task Schdule","Taskschd.msc"] 92 | ,["Services","services.msc"] 93 | ,[] 94 | ,["Regedit","regedit"] 95 | ,["gpedit.msc","gpedit.msc"] 96 | ,[] 97 | ,["Edit HOSTS","Sys.Network.EditHOSTS"] 98 | ,["Flush DNS","ipconfig /flushdns"]]) 99 | 100 | xMenu.Add("QuickAppMenu" 101 | ,[["Notepad","notepad"] 102 | ,["Paint","mspaint"] 103 | ,["Calculator","calc"] 104 | ,[] 105 | ,["Screen Keyboard","osk"]]) 106 | 107 | xMenu.Add("GreatMenu" 108 | ,[["xClipboard`t&x","xClipboard.ShowAllClips"] 109 | ,["Window Info","WinMenu.Show"] 110 | ,["Cursor Info`t&i","Sys.Cursor.Info"] 111 | ,[] 112 | ,["Quick Apps`t&a",,{"sub":"QuickAppMenu"}] 113 | ,[] 114 | ,["Screen`t&s" 115 | ,[["Monitor off`t&c","Sys.Screen.Off"] 116 | ,["Lock && MonitorOff`t&l","Sys.Power.LockAndMonitoroff"]]] 117 | ,["System",,{"sub":"System"}]]) 118 | 119 | ; move mouse to top-right of screen and right click, this menu shows 120 | ; 鼠标移到屏幕右上角并右击时出现的菜单 121 | xMenu.Add("ScreenRTMenu" 122 | ,[["Task Manager","taskmgr"] 123 | ,["Resource Monitor","resmon"] 124 | ,["System",,{"sub":"System"}]]) 125 | 126 | ; 两个函数供调用 127 | xmenu_show_great_menu() 128 | { 129 | xMenu.Show("GreatMenu", A_ScreenWidth/2, A_ScreenHeight/2) 130 | } 131 | xmenu_show_screen_rt_menu() 132 | { 133 | xMenu.Show("ScreenRTMenu") 134 | } 135 | 136 | 137 | /* 138 | 以下是快捷键的定义 139 | shortcuts definitions 140 | */ 141 | 142 | ; 把两个字符串数组交叉连接起来 143 | str_array_concate(arr, app, deli="") 144 | { 145 | ret := [] 146 | if(arr.MaxIndex()=="") { 147 | arr := [arr] 148 | } 149 | if(app.MaxIndex()=="") { 150 | app := [arr] 151 | } 152 | Loop, % arr.MaxIndex() { 153 | idx1 := A_Index 154 | Loop, % app.MaxIndex() { 155 | idx2 := A_Index 156 | ret.insert(arr[idx1] deli app[idx2]) 157 | } 158 | } 159 | return % ret 160 | } 161 | 162 | register_hotkey(key_name, action, prefix="") 163 | { 164 | global HOTKEY_REGISTER_LIST 165 | trans_key := [] 166 | map1 := {win: "#", ctrl: "^", shift: "+", alt: "!" 167 | ,lwin: "<#", rwin: ">#" 168 | ,lctrl: "<^", rctrl: ">^" 169 | ,lshift: "<+", rshift: ">+" 170 | ,lalt: "!" 171 | ,lclick: "LButton", rclick: "RButton", wheelclick: "MButton" } 172 | ; ,wheel: ["wheelUp", "wheelDown"] } 173 | key_split_arr := StrSplit(key_name, "_") 174 | Loop, % key_split_arr.MaxIndex() 175 | { 176 | cur_symbol := key_split_arr[A_Index] 177 | maped_symbol := map1[cur_symbol] 178 | if(maped_symbol=="") { 179 | trans_key := str_array_concate(trans_key, [cur_symbol]) 180 | } 181 | else if(IsObject(maped_symbol)) { 182 | trans_key := str_array_concate(trans_key, maped_symbol) 183 | } 184 | else { 185 | trans_key := str_array_concate(trans_key, [maped_symbol]) 186 | } 187 | } 188 | prefix_arr := StrSplit(prefix, "-") 189 | prefix_trans_keys := str_array_concate(prefix_arr, trans_key, "|") 190 | Loop, % prefix_trans_keys.MaxIndex() 191 | { 192 | key := prefix_trans_keys[A_Index] 193 | StringUpper, key, key 194 | ; m(key "//" action) 195 | HOTKEY_REGISTER_LIST[key] := action 196 | arr := StrSplit(key, "|") 197 | if(arr[1]!="") { 198 | Hotkey, IF, border_event_evoke() 199 | Hotkey, % arr[2], SUB_HOTKEY_ZONE_BORDER 200 | } 201 | else { 202 | Hotkey, IF 203 | Hotkey, % arr[2], SUB_HOTKEY_ZONE_ANYWAY 204 | } 205 | } 206 | } 207 | 208 | /* 209 | 普通快捷键 210 | */ 211 | if(OneQuick.GetFeatureCfg("hotkey.switch", 0)) 212 | { 213 | For key, value in OneQuick.GetFeatureCfg("hotkey.buildin", {}) 214 | register_hotkey(key, value, "") 215 | } 216 | 217 | /* 218 | 屏幕边缘操作 219 | */ 220 | if(OneQuick.GetFeatureCfg("screen-border.switch", 0)) 221 | { 222 | For border_key, border_action in OneQuick.GetFeatureCfg("screen-border.action", {}) 223 | for key, value in border_action 224 | register_hotkey(key, value, border_key) 225 | } 226 | 227 | /* 228 | setting rember 229 | */ 230 | SETTING_REM := { notepad_ctrl_w_close: OneQuick.GetFeatureCfg("app_enhance.notepad_ctrl_w_close", 0) 231 | ,chrome_scroll_tab: OneQuick.GetFeatureCfg("app_enhance.chrome_scroll_tab", 0) 232 | ,sublime_file_folder: OneQuick.GetFeatureCfg("app_enhance.sublime_file_folder", 0) } 233 | 234 | 235 | ; //////////////////////////////////////////////////////////////// 236 | /* 237 | 以上为程序初始化时运行的代码,只运行一次 238 | 239 | Code above runs just once after OneQuick launch. 240 | the following code defines hotkeys, 241 | they run when you press the hotkey 242 | make sure codes below will not run when OneQuick start 243 | */ 244 | Return 245 | ; //////////////////////////////////////////////////////////////// 246 | 247 | /* 248 | ; HOTKEY evoke 249 | */ 250 | SUB_HOTKEY_ZONE_ANYWAY: 251 | SUB_HOTKEY_ZONE_BORDER: 252 | border_code := Sys.Cursor.CornerPos() 253 | action := HOTKEY_REGISTER_LIST[border_code "|" A_ThisHotkey] 254 | if(action="") { 255 | ; 鼠标移到边缘但触发普通热键时 256 | action := HOTKEY_REGISTER_LIST["|" A_ThisHotkey] 257 | } 258 | run(action) 259 | Return 260 | 261 | #IF border_event_evoke() 262 | #IF 263 | 264 | border_event_evoke() 265 | { 266 | global HOTKEY_REGISTER_LIST 267 | border_code := Sys.Cursor.CornerPos() 268 | key := border_code "|" A_ThisHotkey 269 | StringUpper, key, key 270 | action := HOTKEY_REGISTER_LIST[key] 271 | if(action!="") 272 | return true 273 | } 274 | 275 | 276 | /* 277 | // from old version 278 | #InputLevel 提高{media_play_pause}和另外两个命令的优先级, 279 | 这样,只要在别处定义 280 | $media_play_pause:: 281 | ...... 282 | 这样的命令,就可以全局改变media_play_pause的行为, 283 | 比如针对不同的播放器发送不同的命令 284 | */ 285 | 286 | ; //////////////////////////////////////////////////////////////// 287 | /* 288 | ; 应用增强 289 | ; app enhancement 290 | */ 291 | 292 | /* 293 | ctrl + w 关闭记事本 294 | */ 295 | #if SETTING_REM["notepad_ctrl_w_close"] 296 | $^w::ctrl_w_close_notepad() 297 | #if 298 | 299 | ctrl_w_close_notepad() 300 | { 301 | if(WinActive("ahk_class Notepad")) 302 | { 303 | Winclose, A 304 | } 305 | else 306 | { 307 | send ^w 308 | } 309 | } 310 | 311 | /* 312 | 在chrome标签上滚动滚轮,可切换标签(在不是最大化时仍可用) 313 | scroll on chrome tab to go next/prev tab 314 | */ 315 | #if SETTING_REM["chrome_scroll_tab"] && OnScrollChromeTab() && (!Sys.Cursor.IsPos("LT") && !Sys.Cursor.IsPos("RT")) 316 | wheelup::send ^{PgUp} 317 | wheeldown::send ^{PgDn} 318 | #if 319 | OnScrollChromeTab() 320 | { 321 | if not WinActive("ahk_class Chrome_WidgetWin_1") 322 | return 0 323 | MouseGetPos, X, Y 324 | WinGetPos, wX, wY, wW, wH , A 325 | if ( X > 0 and X < wW and Y-wY > 0 and Y-wY < 45 ) 326 | return 1 327 | else 328 | return 0 329 | } 330 | 331 | /* 332 | 使用sublime时,按win+E 打开当前正在编辑的文件的目录 333 | win + E: (when sublime active) open current edit file folder 334 | */ 335 | #if SETTING_REM["sublime_file_folder"] 336 | #e:: 337 | title := Sys.Win.Title() 338 | if(RegExMatch(title, "^(.*)\\.*- Sublime Text", t)) 339 | run(t1) 340 | Else 341 | run("explorer") 342 | return 343 | #if 344 | 345 | ; ////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /script/OneQuick.feature.default.yaml: -------------------------------------------------------------------------------- 1 | File-Description: 可参考\script\OneQuick.feature.default.yaml文件修改 2 | app_enhance: 3 | chrome_scroll_tab: 1 4 | notepad_ctrl_w_close: 1 5 | sublime_file_folder: 1 6 | hotkey: 7 | switch: 1 8 | buildin: 9 | win_z: xmenu_show_great_menu 10 | ctrl_alt_r: OneQuick.Command_run 11 | win_rclick: WinMenu.Show 12 | shift_wheeldown: "send {PgDn}" 13 | shift_wheelup: "send {PgUp}" 14 | win_t: sys.win.topmost 15 | win_n: notepad 16 | win_shift_l: Sys.Power.LockAndMonitoroff 17 | ctrl_shift_alt_r: OneQuick.Reload 18 | screen-border: 19 | switch: 1 20 | action: 21 | B: 22 | wheelclick: "send #{tab}" 23 | wheeldown: "send ^#{right}" 24 | wheelup: "send ^#{left}" 25 | L-R: 26 | ctrl_shift_wheeldown: "send {end}" 27 | ctrl_shift_wheelup: "send {home}" 28 | shift_wheeldown: "send {pgdn}{pgdn}{pgdn}{pgdn}{pgdn}" 29 | shift_wheelup: "send {pgup}{pgup}{pgup}{pgup}{pgup}" 30 | wheeldown: "send {pgdn}" 31 | wheelup: "send {pgup}" 32 | LT: 33 | rclick: winmenu.show 34 | shift_wheeldown: Sys.Screen.BrightnessDown 35 | shift_wheelup: Sys.Screen.BrightnessUp 36 | wheelclick: "send {volume_mute}" 37 | wheeldown: "Send {volume_down}" 38 | wheelup: "Send {volume_up}" 39 | RT: 40 | rclick: xmenu_show_screen_rt_menu 41 | wheelclick: "send {media_play_pause}" 42 | wheeldown: "send {media_next}" 43 | wheelup: "send {media_prev}" 44 | T: 45 | wheeldown: Sys.Win.GotoNextTab 46 | wheelup: Sys.Win.GotoPreTab 47 | clipboard: 48 | switch: 1 49 | hotkey: 50 | ctrl_shift_x: xClipboard.ShowAllClips 51 | ctrl_shift_c: xClipboard.CopyAndShowMenu 52 | ctrl_shift_v: xClipboard.ShowClipMenu 53 | browser: "Default, Edge, Chrome, IE" 54 | search: "Google/g, baidu/b/百度, baidu_local//百度Local, Bing, weibo/w/微博, zhihu/z/知乎, Bilibili/l/哔哩哔哩, Acfun/a, YouTube/y, netease_music//网易云音乐, douban/d/豆瓣, douban_movie/m/豆瓣电影, qr_code/q/二维码" 55 | ClipsFirstShowNum: 10 56 | ClipsTotalNum: 50 57 | browser_list: 58 | Default: default 59 | Edge: "microsoft-edge:" 60 | Chrome: "chrome.exe" 61 | IE: "iexplore.exe" 62 | search_list: 63 | google: https://www.google.com/search?q=%s 64 | baidu: http://www.baidu.com/s?wd=%s 65 | baidu_local: http://www.baidu.com/s?wd=%s&tn=baidulocal 66 | bing: http://www.bing.com/search?q=%s 67 | qr_code: http://api.qrserver.com/v1/create-qr-code/?data=%s 68 | weibo: http://s.weibo.com/weibo/%s 69 | zhihu: http://www.zhihu.com/search?q=%s 70 | bilibili: http://www.bilibili.com/search?keyword=%s 71 | acfun: http://www.acfun.tv/search/#query=%s 72 | douban: https://www.douban.com/search?q=%s 73 | douban_movie: http://movie.douban.com/subject_search?search_text=%s 74 | guokr: http://www.guokr.com/search/all/?wd=%s 75 | netease_music: http://music.163.com/#/search/m/?s=%s&type=1 76 | youtube: https://www.youtube.com/results?search_query=%s 77 | -------------------------------------------------------------------------------- /script/OneQuick.setting.default.yaml: -------------------------------------------------------------------------------- 1 | _onequick_: 2 | # for old version(0.1.0) check update 3 | version: 0.3.0 4 | version-build: 999 5 | -------------------------------------------------------------------------------- /script/Yaml.ahk: -------------------------------------------------------------------------------- 1 | Yaml(YamlText,IsFile=1,YamlObj=0){ ; Version 1.0.0.17 http://www.autohotkey.com/forum/viewtopic.php?t=70559 2 | static 3 | static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}} 4 | static BackupVars:="LVL,SEQ,KEY,SCA,TYP,VAL,CMT,LFL,CNT",IncompleteSeqMap 5 | local maxLVL:=0,LastContObj:=0,LastContKEY:=0,LinesAdded:=0,_LVLChanged:=0,_LVL,_SEQ,_KEY,_SCA,_TYP,_VAL,_CMT,_LFL,_CNT,_NXT,__LVL,__SEQ,__KEY,__SCA,__TYP,__VAL,__CMT,__LFL,__CNT,__NXT 6 | AutoTrim % ((AutoTrim:=A_AutoTrim)="On")?"Off":"Off" 7 | LVL0:=pYaml:=YamlObj?YamlObj:Object("base",base),__LVL:=0,__LVL0:=0 8 | If IsFile 9 | FileRead,YamlText,%YamlText% 10 | Loop,Parse,YamlText,`n,`r 11 | { 12 | If (!_CNT && (A_LoopField=""||RegExMatch(A_LoopField,"^\s+$"))){ ;&&__KEY=""&&__SEQ="")){ 13 | If ((OBJ:=LVL%__LVL%[""].MaxIndex())&&IsObject(LVL%__LVL%["",OBJ])&&__SEQ){ 14 | If (__KEY!="") 15 | Yaml_Continue(LastContObj:=LVL%__LVL%["",Obj],LastContKEY:=__key,"",__SCA) 16 | else Yaml_Continue(LastContObj:=LVL%__LVL%[""],LastContKEY:=Obj,"",__SCA,__SEQ) 17 | } else If (__SEQ && OBJ){ 18 | Yaml_Continue(LastContObj:=LVL%__LVL%[""],LastContKEY:=OBJ,"",__SCA,__SEQ) 19 | } else If (OBJ){ 20 | Yaml_Continue(LastContObj:=LVL%__LVL%[""],LastContKEY:=OBJ,"",__SCA,1) 21 | } else if (__KEY!="") 22 | Yaml_Continue(LastContObj:=LVL%__LVL%,LastContKEY:=__KEY,"",__SCA) 23 | else LinesAdded-- 24 | LinesAdded++ 25 | Continue 26 | } else If (!_CNT && LastContObj 27 | && ( RegExMatch(A_LoopField,"^(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)") 28 | || RegExMatch(A_LoopField,"^(---)|\s*(-\s)") )){ 29 | If !__SCA 30 | LastContObj[LastContKEY]:=SubStr(LastContObj[LastContKEY],1,-1*LinesAdded) 31 | LastContObj:=0,LastContKEY:=0,LinesAdded:=0 32 | } 33 | If InStr(A_LoopField,"#"){ 34 | If (RegexMatch(A_LoopField,"^\s*#.*") || InStr(A_LoopField,"%YAML")=1) ;Comments only, do not parse 35 | continue 36 | else if Yaml_IsQuoted(LTrim(A_LoopField,"- ")) || RegExMatch(A_LoopField,"(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)\s*([\|\>][+-]?)?\s*(!!\w+\s)?\s*("".+|'.+)$")&&!RegExMatch(A_LoopField,"[^\\]""\s+#") 37 | LoopField:=A_LoopField 38 | else if RegExMatch(A_LoopField,"\s+#.*$","",RegExMatch(A_LoopField,"(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?\s*([\|\>][+-]?)?\s*(!!\w+\s)?\s*("".+""|'.+')?\K")-1) 39 | LoopField:=SubStr(A_LoopField,1,RegExMatch(A_LoopField,"\s+#.*$","",RegExMatch(A_LoopField,"(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?\s*([\|\>][+-]?)?\s*(!!\w+\s)?\s*("".+""|'.+')?\K")-1)-1) 40 | else LoopField:=A_LoopField 41 | } else LoopField:=A_LoopField 42 | If _CNT { 43 | If Yaml_IsSeqMap(RegExReplace(IncompleteSeqMap LoopField,"^(\s+)?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?")) 44 | LoopField:=IncompleteSeqMap LoopField,_CNT:=0,IncompleteSeqMap:="" 45 | else { 46 | IncompleteSeqMap.=LoopField 47 | continue 48 | } 49 | } 50 | If (LoopField="---"){ 51 | Loop % (maxLVL) 52 | LVL%A_Index%:="" 53 | Loop,Parse,BackupVars,`, 54 | __%A_LoopField%:="",__%A_LoopField%0:="" 55 | Loop,Parse,BackupVars,`, 56 | Loop % maxLVL 57 | __%A_LoopField%%A_Index%:="" 58 | maxLVL:=0 59 | __LVL:=0,__LVL0:=0 60 | If !IsObject(pYaml[""]) 61 | pYaml[""]:=LVL0:=Object("base",base) 62 | pYaml[""].Insert(LVL0:=Object("base",base)) 63 | Continue 64 | } else if (LoopField="..."){ 65 | LVL0:=pYaml 66 | Loop % maxLVL 67 | LVL%A_Index%:="" 68 | Loop,Parse,BackupVars,`, 69 | __%A_LoopField%:="",__%A_LoopField%0:="" 70 | Loop,Parse,BackupVars,`, 71 | Loop % maxLVL 72 | __%A_LoopField%%A_Index%:="" 73 | maxLVL:=0 74 | __LVL:=0,__LVL0:=0 75 | Continue 76 | } 77 | If (SubStr(LoopField,0)=":") 78 | LoopField.=A_Space ; add space to force RegEx to match even if the value and space after collon is missing e.g. Object:`n objects item 79 | RegExMatch(LoopField,"S)^(?\s+)?(?-\s)?(?"".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?\s*(?[\|\>][+-]?)?\s*(?!!\w+\s)?\s*(?"".+""|'.+'|.+)?\s*$",_) 80 | If _KEY ;cut off (:) 81 | StringTrimRight,_KEY,_KEY,2 82 | _KEY:=Yaml_UnQuoteIfNeed(_KEY) 83 | If IsVal:=Yaml_IsQuoted(_VAL) 84 | _VAL:=Yaml_UnQuoteIfNeed(_VAL) 85 | ;determine current level 86 | _LVL:=Yaml_S2I(_LVL) 87 | If _LVL-__LVL>1||(_LVL>__LVL&&_LVLChanged) ;&&!(__SEQ&&__KEY!=""&&_KEY!="")) ; (__SEQ?2:1) 88 | { 89 | Loop % (_LVLChanged?_LVL-_LVLChanged:_LVL-__LVL-1) 90 | LoopField:=SubStr(LoopField,SubStr(LoopField,1,1)=A_Tab?1:2) 91 | _LVL:=_LVLChanged?_LVLChanged:__LVL+1,_LVLChanged:=_LVLChanged?_LVLChanged:_LVL ;__LVL%_LVL%:=__LVL%_NXT% ; (__SEQ?2:1) 92 | } else if _LVLChanged 93 | _LVL:=_LVLChanged 94 | else _LVLChanged:=0 95 | If (maxLVL<_LVL) 96 | maxLVL:=_LVL+(_SEQ?1:0) 97 | ; Cut off the leading tabs/spaces conform _LVL 98 | SubStr:=0,Tabs:=0 99 | Loop,Parse,LoopField 100 | If (_LVL*2=SubStr || !SubStr:=SubStr+(A_LoopField=A_Tab?2:1)), Tabs:=Tabs+(A_LoopField=A_Tab?1:0) 101 | break 102 | _LFL:=SubStr(LoopField,SubStr-Tabs+1+(_SEQ?2:0)) 103 | _LFL:=Yaml_UnQuoteIfNeed(_LFL) 104 | _NXT:=_LVL+1 ;next indentation level 105 | __NXT:=_NXT+1 106 | _PRV:=_LVL=0?0:_LVL-1 107 | Loop,Parse,BackupVars,`, 108 | __%A_LoopField%:=__%A_LoopField%%_PRV% 109 | If RegExMatch(_LFL,"^-\s*$"){ 110 | _SEQ:="-",_KEY:="",_VAL:="" 111 | } 112 | If (!IsVal && !_CNT && (_CNT:=Yaml_Incomplete(Trim(_LFL))||Yaml_Incomplete(Trim(_VAL)))){ 113 | IncompleteSeqMap:=LoopField 114 | continue 115 | } 116 | If (_LVL<__LVL){ ;Reset Objects and Backup vars 117 | Loop % (maxLVL) 118 | If (A_Index>_LVL){ 119 | Loop,Parse,BackupVars,`, 120 | __%A_LoopField%%maxLVL%:="" 121 | LVL%A_Index%:="",maxLVL:=maxLVL-1 122 | } 123 | If (_LVL=0 && !__LVL:=__LVL0:=0) 124 | Loop,Parse,BackupVars,`, 125 | __%A_LoopField%:="",__%A_LoopField%0:="" 126 | } 127 | If (_SEQ&&_LVL>__LVL&&(__VAL!=""||__SCA)) 128 | _SEQ:="",_KEY:="",_VAL:="",_LFL:="- " _LFL 129 | If (__CNT)||(_LVL>__LVL&&(__KEY!=""&&_KEY="")&&(__VAL!=""||__SCA))||(__SEQ&&__SCA) 130 | _KEY:="",_VAL:="" 131 | If (__CNT||(_LVL>__LVL&&(__KEY!=""||(__SEQ&&(__LFL||__SCA)&&!Yaml_IsSeqMap(__LFL)))&&!(_SEQ||_KEY!=""))){ 132 | If ((OBJ:=LVL%__LVL%[""].MaxIndex())&&IsObject(LVL%__LVL%["",OBJ])&&__SEQ){ 133 | If __KEY!= 134 | Yaml_Continue(LVL%__LVL%["",Obj],__key,_LFL,__SCA),__CNT:=Yaml_SeqMap(LVL%__LVL%["",OBJ],__KEY,LVL%__LVL%["",OBJ,__KEY])?"":__CNT 135 | else Yaml_Continue(LVL%__LVL%[""],Obj,_LFL,__SCA,__SEQ),__CNT:=Yaml_SeqMap(LVL%__LVL%[""],OBJ,LVL%__LVL%["",OBJ],__SEQ)?"":__CNT 136 | } else If (__SEQ && OBJ){ 137 | Yaml_Continue(LVL%__LVL%[""],Obj,_LFL,__SCA,__SEQ) 138 | __CNT:=Yaml_SeqMap(LVL%__LVL%[""],OBJ,LVL%__LVL%["",OBJ],__SEQ)?"":__CNT 139 | } else If (OBJ && __KEY=""){ 140 | Yaml_Continue(LVL%__LVL%[""],OBJ,_LFL,__SCA,1) 141 | __CNT:=Yaml_SeqMap(LVL%__LVL%[""],OBJ,LVL%__LVL%["",OBJ],1)?"":__CNT 142 | } else { 143 | Yaml_Continue(LVL%__LVL%,__KEY,_LFL,__SCA) 144 | __CNT:=Yaml_SeqMap(LVL%__LVL%,__KEY,LVL%__LVL%[__KEY])?"":__CNT 145 | } 146 | Continue 147 | } 148 | ;Create sequence or map 149 | If (__SEQ&&(_LVL>__LVL)&&_KEY!=""&&__KEY!=""){ 150 | OBJ:=LVL%__LVL%[""].MaxIndex() 151 | If _SEQ { 152 | If !Yaml_SeqMap(LVL%_LVL%["",OBJ,__KEY,""],_KEY,_VAL){ 153 | If !IsObject(LVL%__LVL%["",OBJ,__KEY,""]) 154 | LVL%__LVL%["",OBJ,__KEY,""]:={base:base} 155 | LVL%__LVL%["",OBJ,__KEY,""].Insert({(_KEY):_VAL!=""?_VAL:(LVL%_NXT%:={base:base}),base:base}) 156 | } 157 | } else If !Yaml_SeqMap(LVL%_LVL%["",OBJ],_KEY,_VAL){ 158 | LVL%__LVL%["",OBJ,_KEY]:=_VAL!=""?_VAL:(LVL%_NXT%:={base:base}) 159 | } 160 | If _VAL!= 161 | continue 162 | } else If (_SEQ){ 163 | If !IsObject(LVL%_LVL%[""]) 164 | LVL%_LVL%[""]:=Object("base",base) 165 | While (SubStr(_LFL,1,2)="- "){ 166 | _LFL:=SubStr(_LFL,3),_KEY:=(_KEY!="")?_LFL:=SubStr(_KEY,3):_KEY,LVL%_LVL%[""].Insert(LVL%_NXT%:=Object("",Object("base",base),"base",base)),_LVL:=_LVL+1,_NXT:=_NXT+1,__NXT:=_NXT+1,_PRV:=_LVL-1,maxLVL:=(maxLVL<_LVL)?_LVL:maxLVL 167 | Loop,Parse,BackupVars,`, 168 | __%A_LoopField%:=_%A_LoopField% 169 | ,__%A_LoopField%%_PRV%:=_%A_LoopField% 170 | } 171 | If (_KEY="" && _VAL="" && !IsVal){ 172 | If !Yaml_SeqMap(LVL%_LVL%[""],"",_LFL) 173 | LVL%_LVL%[""].Insert(LVL%_NXT%:=Object("base",base)) 174 | } else If (_KEY!="") { 175 | LVL%_LVL%[""].Insert(LVL%__NXT%:=Object(_KEY,LVL%_NXT%:=Object("base",base),"base",base)) 176 | If !Yaml_SeqMap(LVL%__NXT%,_KEY,_VAL){ 177 | LVL%_LVL%[""].Remove() 178 | LVL%_LVL%[""].Insert(LVL%__NXT%:=Object(_KEY,(_VAL!=""||IsVal)?_VAL:LVL%_NXT%:=Object("base",base),"base",base)) 179 | } 180 | } else { 181 | If !Yaml_SeqMap(LVL%_LVL%[""],"",_LFL) 182 | LVL%_LVL%[""].Insert(_LFL) 183 | } 184 | If !LVL%_LVL%[""].MaxIndex() 185 | LVL%_LVL%.Remove("") 186 | } else if (_KEY!=""){ 187 | If (__SEQ && _LVL>__LVL) { 188 | If (OBJ:=LVL%_PRV%[""].MaxIndex())&&IsObject(LVL%_PRV%["",OBJ]){ 189 | If !Yaml_SeqMap(LVL%_PRV%["",OBJ],_KEY,_VAL) 190 | LVL%_PRV%["",OBJ,_KEY]:=(_VAL!=""||IsVal)?_VAL:(LVL%_NXT%:=Object("base",base)) 191 | } else { 192 | LVL%_PRV%[""].Insert(Object(_KEY,(_VAL!=""||IsVal)?_VAL:(LVL%_NXT%:=Object("base",base)),"base",base)) 193 | Yaml_SeqMap(LVL%_PRV%["",OBJ?OBJ+1:1],_KEY,_VAL) 194 | } 195 | } else 196 | If !Yaml_SeqMap(LVL%_LVL%,_KEY,_VAL) 197 | LVL%_LVL%[_KEY]:=_VAL!=""?_VAL:(LVL%_NXT%:=Object("base",base)) 198 | } else if (_LVL>__LVL && (__KEY!="")) { 199 | If (__VAL!="" || __SCA){ 200 | Yaml_Continue(LVL%__LVL%,__KEY,_LFL,__SCA) 201 | Yaml_SeqMap(LVL%__LVL%,__KEY,LVL%__LVL%[__KEY]) 202 | Continue 203 | } else { 204 | If !Yaml_SeqMap(LVL%__LVL%[__KEY],_KEY,_VAL) ;!!! no Scalar??? 205 | LVL%__LVL%[__KEY,_KEY]:=_VAL 206 | Continue 207 | } 208 | } else { 209 | If (_LVL>__LVL&&(OBJ:=LVL%__LVL%[""].MaxIndex())&&IsObject(LVL%__LVL%["",OBJ])&&__SEQ){ 210 | If __CNT 211 | Yaml_Continue(LVL%__LVL%[""],LVL%__LVL%[""].MaxIndex(),_LFL,__SCA,1) 212 | If (__CNT:=Yaml_SeqMap(LVL%__LVL%[""],"",_LFL)?"":1) 213 | LVL%__LVL%[""].Insert(_LFL) 214 | } else { 215 | If !IsObject(LVL%_LVL%[""]) 216 | LVL%_LVL%[""]:=Object("base",base) 217 | If __CNT 218 | Yaml_Continue(LVL%__LVL%[""],LVL%__LVL%[""].MaxIndex(),_LFL,__SCA,1) 219 | If (__CNT:=Yaml_SeqMap(LVL%_LVL%[""],"",_LFL)?"":1) 220 | LVL%_LVL%[""].Insert(_LFL) 221 | } 222 | Continue 223 | } 224 | Loop,Parse,BackupVars,`, 225 | __%A_LoopField%:=_%A_LoopField% 226 | ,__%A_LoopField%%_LVL%:=_%A_LoopField% 227 | } 228 | If (LastContObj && !__SCA) 229 | LastContObj[LastContKEY]:=SubStr(LastContObj[LastContKEY],1,-1*LinesAdded) 230 | AutoTrim %AutoTrim% 231 | Loop,Parse,BackupVars,`, 232 | If !(__%A_LoopField%:="") 233 | Loop % maxLVL 234 | __%A_LoopField%%A_Index%:="" 235 | Return pYaml,pYaml.base:=base 236 | } 237 | Yaml_Save(obj,file,level=""){ 238 | FileMove,% file,% file ".bakupyml",1 239 | FileAppend,% obj.Dump(),% file 240 | If !ErrorLevel 241 | FileDelete,% file ".bakupyml" 242 | else { 243 | FileMove,% file ".bakupyml",% file 244 | MsgBox,0, Error creating file, old file was restored. 245 | } 246 | } 247 | Yaml_Call(NotSupported,f,p*){ 248 | If (p.MaxIndex()>1){ 249 | Loop % p.MaxIndex() 250 | If A_Index>1 251 | f:=f[""][p[A_Index-1]] 252 | } 253 | Return (!p.MaxIndex()?f[""].MaxIndex():f[""][p[p.MaxIndex()]]) 254 | } 255 | Yaml_Merge(obj,merge){ 256 | for k,v in merge 257 | { 258 | If IsObject(v){ 259 | If obj.HasKey(k){ 260 | If IsObject(obj[k]) 261 | Yaml_Merge(obj[k],v) 262 | else obj[k]:=v 263 | } else obj[k]:=v 264 | } else obj[k]:=v 265 | } 266 | } 267 | Yaml_Add(O,Yaml="",IsFile=0){ 268 | static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}} 269 | If Yaml_IsSeqMap(Trim(Yaml)){ 270 | If !IsObject(O[""]) 271 | O[""]:=Object("base",base) 272 | Yaml_SeqMap(O[""],"",Yaml) 273 | } else Yaml(Yaml,IsFile,O) 274 | } 275 | Yaml_Dump(O,J="",R=0,Q=0){ 276 | static M1:="{",M2:="}",S1:="[",S2:="]",N:="`n",C:=", ",S:="- ",E:="",K:=": " 277 | local dump:="",M,MX,F,I,key,value 278 | If (J=0&&!R) 279 | dump.= S1 280 | for key in O 281 | M:=A_Index 282 | If IsObject(O[""]){ 283 | M-- 284 | for key in O[""] 285 | MX:=A_Index 286 | If IsObject(O[""][""]) 287 | MX-- 288 | If O[""].MaxIndex() 289 | for key, value in O[""] 290 | { 291 | If key= 292 | continue 293 | I++ 294 | F:=IsObject(value)?(IsObject(value[""])?"S":"M"):E 295 | If (J!=""&&J<=R){ 296 | dump.=(F?(%F%1 Yaml_Dump(value,J,R+1,F) %F%2):Yaml_EscIfNeed(value)) (I=MX&&!M?E:C) ;(Q="S"&&I=1?S1:E)(Q="S"&&I=MX?S2:E) 297 | } else if F,dump:=dump N Yaml_I2S(R) S 298 | dump.= (J!=""&&J<=(R+1)?%F%1:E) Yaml_Dump(value,J,R+1,F) (J!=""&&J<=(R+1)?%F%2:E) 299 | else { 300 | ; If RegexMatch(value,"[\x{007F}-\x{FFFF}""\{\[']|:\s|\s#") 301 | dump .= Yaml_EscIfNeed(value) 302 | ; else { 303 | ; value:= (value=""?"''":RegExReplace(RegExReplace(Value,"m)^(.*[\r\n].*)$","|" (SubStr(value,-1)="`n`n"?"+":SubStr(value,0)=N?"":"-") "`n$1"),"ms)(*ANYCRLF)\R",N Yaml_I2S(R+1))) 304 | ; StringReplace,value,value,% N Yaml_I2S(R+1) N Yaml_I2S(R+1),% N Yaml_I2S(R+1),A 305 | ; dump.=value 306 | ; } 307 | } 308 | } 309 | } 310 | I=0 311 | for key, value in O 312 | { 313 | If key= 314 | continue 315 | I++ 316 | F:=IsObject(value)?(IsObject(value[""])?"S":"M"):E 317 | If (J=0&&!R) 318 | dump.= M1 319 | If (J!=""&&J<=R){ 320 | dump.=(Q="S"&&I=1?M1:E) Yaml_EscIfNeed(key) K 321 | dump.=F?(%F%1 Yaml_Dump(value,J,R+1,F) %F%2):Yaml_EscIfNeed(value) 322 | dump.=(Q="S"&&I=M?M2:E) (J!=0||R?(I=M?E:C):E) 323 | } else if F,dump:=dump N Yaml_I2S(R) Yaml_EscIfNeed(key) K 324 | dump.= (J!=""&&J<=(R+1)?%F%1:E) Yaml_Dump(value,J,R+1,F) (J!=""&&J<=(R+1)?%F%2:E) 325 | else { 326 | ; If RegexMatch(value,"[\x{007F}-\x{FFFF}""\{\['\t]|:\s|\s#") 327 | dump .= Yaml_EscIfNeed(value) 328 | ; else { 329 | ; value:= (value=""?"''":RegExReplace(RegExReplace(Value,"m)^(.*[\r\n].*)$","|" (SubStr(value,-1)="`n`n"?"+":SubStr(value,0)="`n"?"":"-") "`n$1"),"ms)(*ANYCRLF)\R","`n" Yaml_I2S(R+1))) 330 | ; StringReplace,value,value,% "`n" Yaml_I2S(R+1) "`n" Yaml_I2S(R+1),% "`n" Yaml_I2S(R+1),A 331 | ; dump.= value 332 | ; } 333 | } 334 | If (J=0&&!R){ 335 | dump.=M2 (I]")||RegExMatch(s,"m)\s$")||RegExMatch(s,"m)[\x{7F}-\x{7FFFFFFF}]") 416 | return ("""" . Yaml_CharUni(s) . """") 417 | else return s 418 | } 419 | Yaml_IsQuoted(ByRef s){ 420 | return InStr(".''."""".","." SubStr(Trim(s),1,1) SubStr(Trim(s),0) ".")?1:0 421 | } 422 | Yaml_UnQuoteIfNeed(s){ 423 | s:=Trim(s) 424 | If !(SubStr(s,1,1)=""""&&SubStr(s,0)="""") 425 | return (SubStr(s,1,1)="'"&&SubStr(s,0)="'")?SubStr(s,2,StrLen(s)-2):s 426 | else return Yaml_UniChar(SubStr(s,2,StrLen(s)-2)) 427 | } 428 | Yaml_S2I(str){ 429 | local idx:=0 430 | Loop,Parse,str 431 | If (A_LoopField=A_Tab) 432 | idx++ 433 | else if !Mod(A_index,2) 434 | idx++ 435 | Return idx 436 | } 437 | Yaml_I2S(idx){ 438 | Loop % idx 439 | str .= " " 440 | Return str 441 | } 442 | Yaml_Continue(Obj,key,value,scalar="",isval=0){ 443 | If !IsObject(isObj:=obj[key]) 444 | v:=isObj 445 | If scalar { 446 | StringTrimLeft,scaopt,scalar,1 447 | scalar:=Asc(scalar)=124?"`n":" " 448 | } else scalar:=" ",scaopt:="-" 449 | temp := (value=""?"`n":(SubStr(v,0)="`n"&&scalar="`n"?"":(v=""?"":scalar))) value (scaopt!="-"?(v&&value=""?"`n":""):"") 450 | obj[key]:=Yaml_UnQuoteIfNeed(v temp) 451 | } 452 | Yaml_Quote(ByRef L,F,Q,B,ByRef E){ 453 | Return (F="\"&&!E&&(E:=1))||(E&&!(E:=0)&&(L:=L ("\" F))) 454 | } 455 | Yaml_SeqMap(o,k,v,isVal=0){ 456 | v:=Trim(v,A_Tab A_Space "`n"),m:=SubStr(v,1,1) SubStr(v,0) 457 | If Yaml_IsSeqMap(v) 458 | return m="[]"?Yaml_Seq(o,k,SubStr(v,2,StrLen(v)-2),isVal):m="{}"?Yaml_Map(o,k,SubStr(v,2,StrLen(v)-2),isVal):0 459 | } 460 | Yaml_Seq(obj,key,value,isVal=0){ 461 | static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}} 462 | ContinueNext:=0 463 | If (obj=""){ 464 | If (SubStr(value,0)!="]") 465 | Return 0 466 | else 467 | value:=SubStr(value,2,StrLen(value)-2) 468 | } else { 469 | If (key=""){ 470 | obj.Insert(Object("",cObj:=Object("base",base),"base",base)) 471 | } else if (isval && IsObject(obj[key,""])){ 472 | cObj:=obj[key,""] 473 | } else obj[key]:=Object("",cObj:=Object("base",base),"base",base) 474 | } 475 | Count:=StrLen(value) 476 | Loop,Parse,value 477 | { 478 | If ((Quote=""""&&Yaml_Quote(LF,A_LoopField,Quote,Bracket,Escape)) || (ContinueNext && !ContinueNext:=0)) 479 | Continue 480 | If (Quote){ 481 | If (A_LoopField=Quote){ 482 | Quote= 483 | If Bracket 484 | LF.= A_LoopField 485 | else LF:=SubStr(LF,2) 486 | Continue 487 | } 488 | LF .= A_LoopField 489 | continue 490 | } else if (!Quote&&InStr("""'",A_LoopField)){ 491 | Quote:=A_LoopField 492 | If !Bracket 493 | VQ:=Quote 494 | LF.=A_LoopField 495 | Continue 496 | } else if (!Quote&&Bracket){ 497 | If (Asc(A_LoopField)=Asc(Bracket)+2) 498 | BCount-- 499 | else if (A_LoopField=Bracket) 500 | BCount++ 501 | If (BCount=0) 502 | Bracket= 503 | LF .= A_LoopField 504 | Continue 505 | } else if (!Quote&&!Bracket&&InStr("[{",A_LoopField)){ 506 | Bracket:=A_LoopField 507 | BCount:=1 508 | LF.=A_LoopField 509 | Continue 510 | } 511 | If (A_Index=Count) 512 | LF .= A_LoopField 513 | else if (!Quote&&!Bracket&&A_LoopField=","&&(!InStr("0123456789",SubStr(value,A_Index-1,1)) | !InStr("0123456789",SubStr(value,A_Index+1,1)))){ 514 | ContinueNext:=SubStr(value,A_Index+1,1)=A_Space||SubStr(value,A_Index+1,1)=A_Tab 515 | LF:=LF 516 | } else { 517 | LF .= A_LoopField 518 | continue 519 | } 520 | If (obj=""){ 521 | If !VQ 522 | If (Asc(LF)=91 && !Yaml_Seq("","",LF)) 523 | ||(Asc(LF)=123 && !Yaml_Map("","",LF)) 524 | Return 0 525 | } else { 526 | If (VQ || !Yaml_SeqMap(cObj,"",LF)) 527 | cObj.Insert(VQ?Yaml_UniChar(LF):Trim(LF)) 528 | } 529 | LF:="",VQ:="" 530 | } 531 | If (LF){ 532 | If (obj=""){ 533 | If !VQ 534 | If (Asc(LF)=91 && !Yaml_Seq("","",LF))||(Asc(LF)=123 && !Yaml_Map("","",LF)) 535 | Return 0 536 | } else If (VQ || !Yaml_SeqMap(cObj,"",LF)) 537 | cObj.Insert(VQ?Yaml_UniChar(LF):Trim(LF)) 538 | } 539 | Return (obj=""?(Quote Bracket=""):1) 540 | } 541 | Yaml_Map(obj,key,value,isVal=0){ 542 | static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}} 543 | ContinueNext:=0 544 | If (obj=""){ 545 | If (SubStr(value,0)!="}") 546 | Return 0 547 | else 548 | value:=SubStr(value,2,StrLen(value)-2) 549 | } else { 550 | If (key="") 551 | obj.Insert(cObj:=Object("base",base)) 552 | else obj[key]:=(cObj:=Object("base",base)) 553 | } 554 | Count:=StrLen(value) 555 | Loop,Parse,value 556 | { 557 | 558 | If ((Quote=""""&&Yaml_Quote(LF,A_LoopField,Quote,Bracket,Escape)) || (ContinueNext && !ContinueNext:=0)) 559 | Continue 560 | If (Quote){ 561 | If (A_LoopField=Quote){ 562 | Quote= 563 | LF.=A_LoopField 564 | } else LF .= A_LoopField 565 | continue 566 | } else if (!Quote&&(k=""||v="")&&InStr("""'",A_LoopField)){ 567 | Quote:=A_LoopField 568 | If (k && !Bracket) 569 | VQ:=Quote 570 | else if !Bracket 571 | KQ:=Quote 572 | LF.=Quote 573 | Continue 574 | } else If (k!=""&&LF=""&&InStr("`n`r `t",A_LoopField)){ 575 | Continue 576 | } 577 | If (!Quote&&Bracket){ 578 | If (Asc(A_LoopField)=Asc(Bracket)+2) 579 | BCount-- 580 | else if (A_LoopField=Bracket) 581 | BCount++ 582 | If (BCount=0) 583 | Bracket= 584 | LF .= A_LoopField 585 | Continue 586 | } else if (!Quote&&!Bracket&&InStr("[{",A_LoopField)){ 587 | Bracket:=A_LoopField 588 | BCount=1 589 | LF.=A_LoopField 590 | Continue 591 | } 592 | If (A_Index=Count&&k!=""){ 593 | v:=LF A_LoopField 594 | v:=Trim(v) 595 | If (InStr("""'",SubStr(v,0))&&SubStr(v,1,1)=SubStr(v,0)) 596 | v:=SubStr(v,2,StrLen(v)-2) 597 | } else If (!Quote&&!Bracket&&k!=""&&A_LoopField=","&&SubStr(value,A_Index+1,1)=A_Space){ 598 | ContinueNext:=1 599 | LF:=Trim(LF) 600 | If VQ 601 | LF:=SubStr(LF,2,StrLen(LF)-2) 602 | v:=LF,LF:="" 603 | } else if (!Quote&&!Bracket&&k=""&&A_LoopField=":"){ 604 | LF:=Trim(LF) 605 | If (InStr("""'",SubStr(LF,0))&&SubStr(LF,1,1)=SubStr(LF,0)) 606 | LF:=SubStr(LF,2,StrLen(LF)-2) 607 | k:=LF,LF:="" 608 | continue 609 | } else { 610 | LF .= A_LoopField 611 | continue 612 | } 613 | If (obj=""){ 614 | If VQ= 615 | If (Asc(v)=91 && !Yaml_Seq("","",v)) 616 | ||(Asc(v)=123 && !Yaml_Map("","",v)) 617 | Return 0 618 | } else { 619 | If (VQ || !Yaml_SeqMap(cObj,k,v)) 620 | cObj[KQ?Yaml_UniChar(k):k]:=(VQ?Yaml_UniChar(v):Trim(v)) 621 | } 622 | k:="",v:="",VQ:="",KQ:="" 623 | } 624 | If (k){ 625 | If (obj=""){ 626 | If (Asc(LF)=91 && !Yaml_Seq("","",LF))||(Asc(LF)=123 && !Yaml_Map("","",LF)) 627 | Return 0 628 | } else { 629 | LF:=Trim(LF) 630 | If (VQ) 631 | LF:=SubStr(LF,2,StrLen(LF)-2),cObj[k]:=Yaml_UniChar(LF) 632 | else If (!Yaml_SeqMap(cObj,k,LF)) 633 | cObj[k]:=Trim(LF) 634 | } 635 | } 636 | Return (obj=""?(Quote Bracket=""):1) 637 | } 638 | Yaml_Incomplete(value){ 639 | return (Asc(Trim(value,"`n" A_Tab A_Space))=91 && !Yaml_Seq("","",Trim(value,"`n" A_Tab A_Space))) 640 | || (Asc(Trim(value,"`n" A_Tab A_Space))=123 && !Yaml_Map("","",Trim(value,"`n" A_Tab A_Space))) 641 | } 642 | Yaml_IsSeqMap(value){ 643 | return (Asc(Trim(value,"`n" A_Tab A_Space))=91 && Yaml_Seq("","",Trim(value,"`n" A_Tab A_Space))) 644 | || (Asc(Trim(value,"`n" A_Tab A_Space))=123 && Yaml_Map("","",Trim(value,"`n" A_Tab A_Space))) 645 | } -------------------------------------------------------------------------------- /script/update_list.json: -------------------------------------------------------------------------------- 1 | [{"name":"script\\OneQuick.ahk"},{"name":"script\\OneQuick.Core.ahk"},{"name":"script\\OneQuick.feature.default.yaml"},{"name":"script\\OneQuick.setting.default.yaml"},{"name":"script\\user_guide.ahk"},{"name":"script\\version.yaml"},{"name":"lang\\cn.ini"},{"name":"lang\\en.ini"},{"name":"README.md"},{"name":"\u5B89\u88C5\u8BF4\u660E.txt"}] 2 | -------------------------------------------------------------------------------- /script/user_guide.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | @author: XJK 3 | @github: https://github.com/XUJINKAI 4 | 5 | OneQuick User Guide 6 | */ 7 | 8 | SplitPath, A_ScriptDir, , workdir 9 | SetWorkingDir, %workdir% 10 | #NoTrayIcon 11 | #Include %A_ScriptDir% 12 | #Include OneQuick.Core.ahk 13 | 14 | msg_hello = 15 | ( 16 | 欢迎使用OneQuick, 17 | OneQuick是一款快捷键工具,通过一个简单的配置文件, 18 | 你可以得到屏幕边缘操作,剪贴板记录,快速搜索等诸多增强功能。 19 | ) 20 | 21 | guide_obj := [["", msg_hello] 22 | ,["", "尝试一下:将鼠标移到屏幕左上角并滚动滚轮,`n效果:快速调节音量"] 23 | ,["", "尝试一下:将鼠标移到屏幕左或右边缘,然后滚轮,`n效果:翻页(相当于PageUp或PageDown)"] 24 | ,["", "最后,右击托盘图标,`n你可以`n 查看在线帮助, 了解更多功能、`n 让OneQuick随系统启动、`n 打开功能配置文件、`n ...。`n祝使用愉快~"]] 25 | parse_guide_obj(guide_obj) 26 | ExitApp 27 | 28 | parse_guide_obj(obj) 29 | { 30 | Loop, % obj.MaxIndex() 31 | { 32 | line := obj[A_Index] 33 | m(line[2]) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /script/version.yaml: -------------------------------------------------------------------------------- 1 | # can't read first line for unknown reason (maybe utf8 BOM) 2 | memo-for-author: "1.this version file; 2.upload count file; 3.generate update_list.json; 4.tag version -> push commit -> zip files -> upload release;" 3 | program: OneQuick 4 | version: 1.2.4 5 | desc-major: Pro版功能正在微软应用商店【限免】中!`n请前往官网OneQuick.org,或在微软应用商店搜索OneQuick。`n【AHK版已停止更新】 6 | desc-minor: Pro版功能正在微软应用商店【限免】中!`n请前往官网OneQuick.org,或在微软应用商店搜索OneQuick。`n【AHK版已停止更新】 7 | desc-revision: Pro版功能正在微软应用商店【限免】中!`n请前往官网OneQuick.org,或在微软应用商店搜索OneQuick。`n【AHK版已停止更新】 8 | auto-update-version: 0.3.0 9 | winrar-path: "C:\\Program Files\\WinRAR\\WinRAR.exe" 10 | zip-path-list: "AHK icon script lang \"OneQuick Launcher.exe\" README.md 安装说明.txt" 11 | update-path: 12 | - script\* 13 | - !script\update_list.json 14 | - !script\JSON.ahk 15 | - !script\Yaml.ahk 16 | - lang\* 17 | - README.md 18 | - 安装说明.txt 19 | -------------------------------------------------------------------------------- /tool/ABOUT.txt: -------------------------------------------------------------------------------- 1 | /tool 文件夹可以放一些小工具来由OneQuick调用 2 | 3 | 比如display.exe (http://noeld.com/programs.asp#Display)可以旋转屏幕, 4 | 将display.exe复制到tool文件夹中,就可以在OneQuick中调用Sys.Screen.RotateCW()和Sys.Screen.RotateCCW() 将屏幕顺时针或逆时针旋转。 5 | 6 | psshutdown.exe (https://technet.microsoft.com/en-us/sysinternals/psshutdown.aspx)可以使计算机待机, 7 | 将psshutdown.exe复制到tool文件夹中,可以在OneQuick中调用Sys.Power.Standby() 使计算机待机。 -------------------------------------------------------------------------------- /安装说明.txt: -------------------------------------------------------------------------------- 1 | ********************* 2 | OneQuick 3 | XJK:https://github.com/XUJINKAI/OneQuick 4 | ********************* 5 | 6 | 运行OneQuick Launcher.exe即可。 7 | 功能列表请右击托盘图标打开在线帮助查看。或用记事本打开README.md查看。 8 | 9 | 注: 10 | 1. 若电脑没安装autohotkey,会先安装再运行,此过程全自动无需再做操作。 11 | 2. 若电脑已经安装autohotkey,则会启动OneQuick。 12 | 已安装autohotkey的电脑,第一次使用的话建议运行一次AHK文件夹下的EnableUIAccess2AHK.ahk,否则OneQuick可能对某些高权限应用无效(如任务管理器)。 13 | --------------------------------------------------------------------------------