diff --git a/App-ScreenRotate.ahk b/App-ScreenRotate.ahk new file mode 100644 index 0000000..eddca09 --- /dev/null +++ b/App-ScreenRotate.ahk @@ -0,0 +1,183 @@ + +; SnowstarCyan_Monitor_Libriay +; Updates: +; 2016y 01m 28d +; Created By Snowstar (SnowstarCyan@gmail.com) +; For rotate my screens to play computer games on bed at winter. ~(≧▽≦)~ + +; API Functions +ChangeDisplaySettingsA := DllCall("User32.dll\ChangeDisplaySettingsA", "Ptr", &lpDevMode, "Int", dwflags) +ChangeDisplaySettingsExA := DllCall("User32.dll\ChangeDisplaySettingsExA", "Str", DeviceName, "Ptr", &lpDevMode, "Ptr", HWND, "Int", dwflags, "Ptr", lParam) +EnumDisplaySettingsA := DllCall("User32.dll\EnumDisplaySettingsA", "Str", DeviceName, "Int", iModeNum, "Ptr", &lpDevMode) +EnumDisplayDevicesA := DllCall("User32.dll\EnumDisplayDevicesA", "Str", DeviceName, "Int", iDevNum, "Ptr", &lpDevMode, "Int", dwflags) + +class DEVMODE_DISPLAY_DEVICE { + __New() { + this.dmSize := 156 + this.dmFields := 0 + } + __Set(key, value) { + if (key == "position_x") || (key == "position_y") + this.dmPosition := &value + else + this[key] := value + } +} + +class DISPLAY_DEVICE { + __New() { + this.cb := 424 + } +} + +_DISPLAY_DEVICE_ATTACHED_TO_DESKTOP := 1 + +Monitor := {} + +Monitor.MapByFunc := Func("MapByFunc") +Monitor.Merge := Func("Merge") +Monitor.GetDevMode := Func("GetDevMode") +Monitor.GetDeviceName := Func("GetDeviceName") +Monitor.RotateDevMode90 := Func("RotateDevMode90") +Monitor.ApplyDevMode := Func("ApplyDevMode") +Monitor.GetDisplayDevices := Func("GetDisplayDevices") +Monitor.RotateOneMonitor := Func("RotateOneMonitor") +Monitor.RotateAllMonitor := Func("RotateAllMonitor") + +MapByFunc(tab, func, params*) { + newtab := {} + for k, v in tab { + newtab[k] := %func%(v, params*) + } + return newtab +} + +Merge(tab1, tab2) { + newtab := {} + for k, v in tab1 { + if (tab1[k] && tab2[k]) { + newtab.push([tab1[k], tab2[k]]) + } + } + return newtab +} + +GetDevMode(deviceName) { + devMode := new DEVMODE_DISPLAY_DEVICE() + success := DllCall("User32.dll\EnumDisplaySettingsA", "Str", deviceName, "Int", -1, "Ptr", devMode) + if (!success) { + MsgBox Can't get current settings. + return null + } + return devMode +} + +GetDeviceName(device) { + return device.DeviceName +} + +RotateDevMode90(devMode, devModeMain) { + New_Orientation := Mod(devMode.displayOrientation + 1, 4) + + ; Calculate new positions + New_position_x := (devModeMain ? devModeMain.pelsHeight - devMode.position_y - devMode.pelsHeight : devMode.position_y) + New_position_y := devMode.position_x + New_pelsWidth := devMode.pelsHeight + New_pelsHeight := devMode.pelsWidth + + devMode.position_x := New_position_x + devMode.position_y := New_position_y + devMode.pelsWidth := New_pelsWidth + devMode.pelsHeight := New_pelsHeight + devMode.displayOrientation := New_Orientation + + return devMode +} + +ApplyDevMode(deviceToDevmode) { + deviceName := deviceToDevmode[1] + devMode := deviceToDevmode[2] + success := DllCall("User32.dll\ChangeDisplaySettingsExA", "Str", deviceName, "Ptr", devMode, "Ptr", 0, "Int", 0, "Ptr", 0) + return success +} + +GetDisplayDevices() { + lsDisplayDevice := [] + iDevNum := 0 + Loop { + lpDisplayDevice := new DISPLAY_DEVICE() + if !DllCall("User32.dll\EnumDisplayDevicesA", "Str", Null, "Int", iDevNum, "Ptr", lpDisplayDevice, "Int", 0) { + break + } + if (lpDisplayDevice.StateFlags & _DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) { + lsDisplayDevice.Push(lpDisplayDevice) + } + iDevNum++ + } + return lsDisplayDevice +} + +RotateOneMonitor(degree, abs := false, deviceName := "") { + devMode := Monitor.GetDevMode(deviceName) + if !devMode { + return + } + + rotCount := Mod((Floor(degree / 90)), 4) + if abs { + rotCount := Mod(rotCount - devMode.displayOrientation, 4) + } + Loop %rotCount% { + devMode := Monitor.RotateDevMode90(devMode) + } + + success := Monitor.ApplyDevMode([deviceName, devMode]) + return success +} + +RotateAllMonitor(degree, abs := false) { + lsDevice := Monitor.GetDisplayDevices() + lsDeviceName := Monitor.MapByFunc(lsDevice, Monitor.GetDeviceName) + + lsDevMode := Monitor.MapByFunc(lsDeviceName, Monitor.GetDevMode) + if !lsDevMode[1] { + MsgBox You can't rotate the `non-screen` + return + } + + rotCount := Mod((Floor(degree / 90)), 4) + if abs { + rotCount := Mod(rotCount - lsDevMode[1].displayOrientation, 4) + } + Loop %rotCount% { + lsDevMode := Monitor.MapByFunc(lsDevMode, Monitor.RotateDevMode90, lsDevMode[1]) + } + + lsDeviceToDevmode := Monitor.Merge(lsDeviceName, lsDevMode) + lsSuccess := Monitor.MapByFunc(lsDeviceToDevmode, Monitor.ApplyDevMode) + return lsSuccess +} + +Monitor.RotateOneMonitor(90) +MsgBox, % GetDisplayDevices().length +return + +#^p:: ScreenRotate() +ScreenRotate(){ + + ; Unit Test + Monitor.RotateOneMonitor(90) + Sleep, 3000 + Monitor.RotateOneMonitor(0, true) + Sleep, 3000 + Monitor.RotateAllMonitor(-90) + Sleep, 3000 + Monitor.RotateAllMonitor(180) + Sleep, 3000 + Monitor.RotateAllMonitor(90, true) + Sleep, 3000 + Monitor.RotateAllMonitor(-90, true) + Sleep, 3000 + Monitor.RotateAllMonitor(0, true) + Sleep, 3000 +} diff --git a/Modules/App-ScreenRotate.ahk b/Modules/App-ScreenRotate.ahk new file mode 100644 index 0000000..4d3676c --- /dev/null +++ b/Modules/App-ScreenRotate.ahk @@ -0,0 +1,195 @@ +; placeholder +; ; +; ; ; SnowstarCyan_Monitor_Libriay +; ; ; Updates: +; ; ; 2016y 01m 28d +; ; ; Created By Snowstar (SnowstarCyan@gmail.com) +; ; ; For rotate my screens to play computer games on bed at winter. ~(≧▽≦)~ +; ; +; ; API Functions for Reference +; ; ChangeDisplaySettingsA := DllCall("User32.dll\ChangeDisplaySettingsA", "Ptr", &lpDevMode, "Int", dwflags) +; ; ChangeDisplaySettingsExA := DllCall("User32.dll\ChangeDisplaySettingsExA", "Str", DeviceName, "Ptr", &lpDevMode, "Ptr", HWND, "Int", dwflags, "Ptr", lParam) +; ; EnumDisplaySettingsA := DllCall("User32.dll\EnumDisplaySettingsA", "Str", DeviceName, "Int", iModeNum, "Ptr", &lpDevMode) +; ; EnumDisplayDevicesA := DllCall("User32.dll\EnumDisplayDevicesA", "Str", DeviceName, "Int", iDevNum, "Ptr", &lpDevMode, "Int", dwflags) + +; ; MsgBox % "EnumDisplayDevicesA" . EnumDisplayDevicesA +; ; +; ; Monitor.RotateOneMonitor(90) +; ; len := GetDisplayDevices().length + +; ; MsgBox, % "len" . len + +; class DEVMODE_DISPLAY_DEVICE { +; __New() { +; this.dmSize := 156 +; this.dmFields := 0 +; } +; __Set(key, value) { +; if (key == "position_x") || (key == "position_y") +; this.dmPosition := &value +; else +; this[key] := value +; } +; } + +; class DISPLAY_DEVICE { +; __New() { +; this.cb := 424 +; } +; } + +; ; _DISPLAY_DEVICE_ATTACHED_TO_DESKTOP := 1 + +; Monitor := {} +; Monitor.MapByFunc := Func("MapByFunc") +; Monitor.Merge := Func("Merge") +; Monitor.GetDeviceMode := Func("GetDeviceMode") +; Monitor.GetDeviceName := Func("GetDeviceName") +; Monitor.RotateDevMode90 := Func("RotateDevMode90") +; Monitor.ApplyDevMode := Func("ApplyDevMode") +; Monitor.GetDisplayDevices := Func("GetDisplayDevices") +; Monitor.RotateOneMonitor := Func("RotateOneMonitor") +; Monitor.RotateAllMonitor := Func("RotateAllMonitor") + +; Monitor.RotateOneMonitor(90) +; MsgBox, % "len: " . GetMonitorCount() + +; ; len := GetDisplayDevices().length + + +; MapByFunc(tab, func, params*) { +; newtab := {} +; for k, v in tab { +; newtab[k] := %func%(v, params*) +; } +; return newtab +; } + +; Merge(tab1, tab2) { +; newtab := {} +; for k, v in tab1 { +; if (tab1[k] && tab2[k]) { +; newtab.push([tab1[k], tab2[k]]) +; } +; } +; return newtab +; } + +; GetDeviceMode(deviceName) { +; devMode := new DEVMODE_DISPLAY_DEVICE() +; success := DllCall("User32.dll\EnumDisplaySettingsA", "Str", deviceName, "Int", -1, "Ptr", devMode) +; if (!success) { +; MsgBox Can't get current settings. +; return null +; } +; return devMode +; } + +; GetDeviceName(device) { +; return device.DeviceName +; } + +; RotateDevMode90(devMode, devModeMain) { +; New_Orientation := Mod(devMode.displayOrientation + 1, 4) + +; ; Calculate new positions +; New_position_x := (devModeMain ? devModeMain.pelsHeight - devMode.position_y - devMode.pelsHeight : devMode.position_y) +; New_position_y := devMode.position_x +; New_pelsWidth := devMode.pelsHeight +; New_pelsHeight := devMode.pelsWidth + +; devMode.position_x := New_position_x +; devMode.position_y := New_position_y +; devMode.pelsWidth := New_pelsWidth +; devMode.pelsHeight := New_pelsHeight +; devMode.displayOrientation := New_Orientation + +; return devMode +; } + +; ApplyDevMode(deviceToDevmode) { +; deviceName := deviceToDevmode[1] +; devMode := deviceToDevmode[2] +; success := DllCall("User32.dll\ChangeDisplaySettingsExA", "Str", deviceName, "Ptr", devMode, "Ptr", 0, "Int", 0, "Ptr", 0) +; return success +; } + +; GetDisplayDevices() { +; lsDisplayDevice := [] +; iDevNum := 0 +; Loop { +; lpDisplayDevice := new DISPLAY_DEVICE() +; if !DllCall("User32.dll\EnumDisplayDevicesA", "ptr", 0, "Int", iDevNum, "Ptr", lpDisplayDevice, "Int", 0) { +; break +; } +; if (lpDisplayDevice.StateFlags & _DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) { +; lsDisplayDevice.Push(lpDisplayDevice) +; } +; MsgBox % "num" . iDevNum +; iDevNum++ +; } +; return lsDisplayDevice +; } + +; RotateOneMonitor(degree, abs := false, deviceName := "") { +; devMode := Monitor.GetDeviceMode(deviceName) +; if !devMode { +; return +; } + +; rotCount := Mod((Floor(degree / 90)), 4) +; if abs { +; rotCount := Mod(rotCount - devMode.displayOrientation, 4) +; } +; Loop %rotCount% { +; devMode := Monitor.RotateDevMode90(devMode) +; } + +; success := Monitor.ApplyDevMode([deviceName, devMode]) +; return success +; } + +; RotateAllMonitor(degree, abs := false) { +; lsDevice := Monitor.GetDisplayDevices() +; lsDeviceName := Monitor.MapByFunc(lsDevice, Monitor.GetDeviceName) + +; lsDevMode := Monitor.MapByFunc(lsDeviceName, Monitor.GetDeviceMode) +; if !lsDevMode[1] { +; MsgBox You can't rotate the `non-screen` +; return +; } + +; rotCount := Mod((Floor(degree / 90)), 4) +; if abs { +; rotCount := Mod(rotCount - lsDevMode[1].displayOrientation, 4) +; } +; Loop %rotCount% { +; lsDevMode := Monitor.MapByFunc(lsDevMode, Monitor.RotateDevMode90, lsDevMode[1]) +; } + +; lsDeviceToDevmode := Monitor.Merge(lsDeviceName, lsDevMode) +; lsSuccess := Monitor.MapByFunc(lsDeviceToDevmode, Monitor.ApplyDevMode) +; return lsSuccess +; } + +; ; return + +; ; #^p:: ScreenRotate() +; ; ScreenRotate(){ + +; ; ; Unit Test +; ; Monitor.RotateOneMonitor(90) +; ; ; Sleep, 3000 +; ; ; Monitor.RotateOneMonitor(0, true) +; ; ; Sleep, 3000 +; ; ; Monitor.RotateAllMonitor(-90) +; ; ; Sleep, 3000 +; ; ; Monitor.RotateAllMonitor(180) +; ; ; Sleep, 3000 +; ; ; Monitor.RotateAllMonitor(90, true) +; ; ; Sleep, 3000 +; ; ; Monitor.RotateAllMonitor(-90, true) +; ; ; Sleep, 3000 +; ; ; Monitor.RotateAllMonitor(0, true) +; ; ; Sleep, 3000 +; ; } diff --git a/Modules/App-ScreenRotate.md b/Modules/App-ScreenRotate.md new file mode 100644 index 0000000..f8db681 --- /dev/null +++ b/Modules/App-ScreenRotate.md @@ -0,0 +1,8 @@ +# Screen Rotate + +使用方法 + +1. OneNote 2016 打开一个窗口,标题写成这样 "剪贴板收集"。 +2. 然后再用 Ctrl + C 复制东西的时候就会自动记到 OneNote 里 +3. 如图 + ![插件-OneNote剪贴板收集器.gif](./插件-OneNote剪贴板收集器.gif) diff --git a/Modules/CLX-Brainstorm.ahk b/Modules/CLX-Brainstorm.ahk index 5ff6f4d..6a0dbd8 100644 --- a/Modules/CLX-Brainstorm.ahk +++ b/Modules/CLX-Brainstorm.ahk @@ -1,10 +1,21 @@ #SingleInstance, Force +; #Requires AutoHotkey v1.1.33 +#Include Lib/AHK-GDIp-Library-Compilation/ahk-v1-1/Gdip_All.ahk ; https://github.com/marius-sucan/AHK-GDIp-Library-Compilation global brainstorming := false global brainstorm_origin := CLX_Config("BrainStorm", "Website", "https://brainstorm.snomiao.com") global brainstormApiKey := CLX_Config("BrainStorm", "Key", "FREE", t("CLX BrainStorm 的功能激活碼,填FREE使用免費版本")) global brainstormLastQuestion := CLX_Config("BrainStorm", "LastQuestion", "", t("Brainstorm 上次提问")) global brainstormStagedAnswer := "" +global brainstormClipType + +global brainstormFilePath := A_ScriptDir "\clipboard-image.jpg" ; Adjust as needed +SplitPath brainstormFilePath,, dir, ext, fnBare +old := dir "\" fnBare "-OLD" "." ext +FileRecycle % old +FileMove % brainstormFilePath, % old + +OnClipboardChange("clipChanged") return @@ -12,9 +23,12 @@ return ; Brainstorm - b:: brainstorm() - +b:: brainstorm_show() - !b:: brainstorm_set_key() + b:: brainstorm_prompt() + +b:: brainstorm_quick_capture() + !b:: brainstorm_prompt("no-prompt") + +!b:: brainstorm_quick_capture("no-prompt") + ^b:: brainstorm_show() + ; ^b:: brainstorm_set_key() #if brainstorming @@ -53,14 +67,48 @@ brainstorm_set_key() brainstorm_copy() { originalClipboard := ClipboardAll + imagePathBeforeCopy := save_clipboard_image() + Clipboard= SendEvent, ^c - ClipWait, 3 ; wait for 3 seconds - content := Clipboard + ; ClipWait, 3 ; wait for 3 seconds + ; content := Clipboard + + ClipWait, 1, 1 ; wait for 1 seconds, wait for anytype, use with ClipboardAll + imagePath := save_clipboard_image() + ; prefix with image path if imagePathBeforeCopy or imagePath + if (imagePathBeforeCopy != "" ) { + content := "![](" . "image.jpg" . ")" . "`n" . Clipboard + } else if (imagePath != "") { + content := "![](" . "image.jpg" . ")" . "`n" . Clipboard + } else { + content := Clipboard + } + Clipboard := originalClipboard - return content + return { question: content, imagePath: imagePathBeforeCopy != "" ? imagePathBeforeCopy : imagePath != "" ? imagePath : "" } } -brainstorm() +brainstorm_capture_window() +{ + ; originalClipboard := ClipboardAll + + ; Clipboard= + ; SendEvent !{PrintScreen} + ; ClipWait, 3 ; wait for 3 seconds + ; content := Clipboard + + ; ClipWait, 3, 1 ; wait for 1 seconds, wait for anytype, use with ClipboardAll + imagePath := save_active_window_image() + if (imagePath != "") { + content := "![](" . "image.jpg" . ")" . "`n" . "" + } else { + content := "" + } + + ; Clipboard := originalClipboard + return { question: content, imagePath: imagePath != "" ? imagePath : "" } +} +brainstorm_quick_capture(skip_prompt:=false) { ; heat up global brainstorm_origin @@ -69,21 +117,79 @@ brainstorm() xhrHeatUp.Open("PUT", endpoint) xhrHeatUp.onreadystatechange := Func("BS_heatUp_onReadyStateChange").Bind(xhr) xhrHeatUp.Send("") - - content := brainstorm_copy() + + clipboardContent := brainstorm_capture_window() + content := clipboardContent.question + imagePath := clipboardContent.imagePath + + ; use ">>>" as default prompt if brainstormLastQuestion is empty + global brainstormLastQuestion + if (brainstormLastQuestion == "") { + brainstormLastQuestion := ">>> this is screenshot, plz help user solve the problem (in the language of in screenshot)" + } + if(skip_prompt) { + cmd := brainstormLastQuestion + }else{ + prompt := "" + prompt .= t("回邮件:选中一段邮件,输入 >> Reply this email") . "`n" + prompt .= t("翻译:选中一段文字,输入 >> Translate to English/翻译到繁体中文/简体中文") . "`n" + prompt .= t("总结:选中一段文字,输入 >> Summary") . "`n" + prompt .= t("提问:选中一段文字,输入 >> Question") . "`n" + prompt .= "--- " . t("以下为提問内容") . " ---`n" . content + InputBox, cmd, % t("请輸入文本指令"), %prompt%, , 500, 600,,,,,% brainstormLastQuestion + } + + ; if escape + if (ErrorLevel == 1) { + Return + } + brainstormLastQuestion := CLX_ConfigSet("BrainStorm", "LastQuestion", cmd) + + msg := Trim(content . "`n`n" . cmd, OmitChars = " `t`n") + + ToolTip, % t("Going to Ask AI") + + global brainstorming + brainstorming := true + brainstorm_questionPost(msg, imagePath) + ToolTip, % t("Asking AI") +} +brainstorm_prompt(skip_prompt=false) +{ + ; heat up + global brainstorm_origin + endpoint := brainstorm_origin . "/ai/chat?ret=polling" + xhrHeatUp := ComObjCreate("Msxml2.XMLHTTP") + xhrHeatUp.Open("PUT", endpoint) + xhrHeatUp.onreadystatechange := Func("BS_heatUp_onReadyStateChange").Bind(xhr) + xhrHeatUp.Send("") + + clipboardContent := brainstorm_copy() + content := clipboardContent.question + imagePath := clipboardContent.imagePath prompt := "" - prompt .= t("'例1:Translate to english:'") . "`n" - prompt .= t("'例2:解釈这句話:'") . "`n" - prompt .= t("'例3:总结5点:'") . "`n" + prompt .= t("回邮件:选中一段邮件,输入 >> Reply this email") . "`n" + prompt .= t("翻译:选中一段文字,输入 >> Translate to English/翻译到繁体中文/简体中文") . "`n" + prompt .= t("总结:选中一段文字,输入 >> Summary") . "`n" + prompt .= t("提问:选中一段文字,输入 >> Question") . "`n" prompt .= "--- " . t("以下为提問内容") . " ---`n" . content - InputBox, cmd, % t("请輸入文本指令"), %prompt%, , 500, 600,,,,,% brainstormLastQuestion + + ; use ">>>" as default prompt if brainstormLastQuestion is empty + if (brainstormLastQuestion == "") { + brainstormLastQuestion := ">>>" + } + if(skip_prompt){ + cmd := brainstormLastQuestion + }else{ + InputBox, cmd, % t("请輸入文本指令"), %prompt%, , 500, 600,,,,,% brainstormLastQuestion + } ; if escape if (ErrorLevel == 1) { Return } - + global brainstormLastQuestion := CLX_ConfigSet("BrainStorm", "LastQuestion", cmd) msg := Trim(content . "`n`n" . cmd, OmitChars = " `t`n") @@ -92,7 +198,7 @@ brainstorm() global brainstorming brainstorming := true - brainstorm_questionPost(msg) + brainstorm_questionPost(msg, imagePath) ToolTip, % t("Asking AI") } BS_heatUp_onReadyStateChange(xhr){ @@ -102,7 +208,7 @@ BS_heatUp_onReadyStateChange(xhr){ ; xhr heatup done } -brainstorm_questionPost(question) +brainstorm_questionPost(question, imagePath) { global brainstorm_origin endpoint := brainstorm_origin . "/ai/chat?ret=polling" @@ -115,7 +221,16 @@ brainstorm_questionPost(question) return } xhr.onreadystatechange := Func("BS_questionPost_onReadyStateChange").Bind(xhr) - xhr.Send(question) + if (imagePath != "") { + formObj := { question: question, image: [imagePath] } + } else { + formObj := { question: question } + } + contentType := "" + CreateFormData(PostData, contentType, formObj) ; convert imagePath to formData dkj + xhr.setRequestHeader("Content-Type", contentType) + xhr.setRequestHeader("Origin", brainstorm_origin) + xhr.Send(PostData) } BS_questionPost_onReadyStateChange(xhr) { @@ -134,12 +249,14 @@ BS_questionPost_onReadyStateChange(xhr) ; ignore 500 error return } - MsgBox, % xhr.status . " " xhr.responseText . " " . t("Unknown Error") + ; ignore unknown error + ; MsgBox, % xhr.status . " " xhr.responseText . " " . t("Unknown Error") return } global questionId := xhr.responseText if (!questionId) { - MsgBox, % t("Fail to ask ai") + ; ignore error + ; MsgBox, % t("Fail to ask ai") return } @@ -172,10 +289,12 @@ tokenAppend_onReadyStateChange(xhra) if (xhra.readyState != 4) { return } + ; drain if (xhra.status != 200) { ; ToolTip ; TrayTip AI Response copied, %brainstorm_response% ; Clipboard:=brainstorm_response + return } @@ -191,7 +310,7 @@ tokenAppend_onReadyStateChange(xhra) global brainstormStagedAnswer brainstormStagedAnswer .= token - ToolTip, % brainstormStagedAnswer + ToolTip, % brainstormStagedAnswer . "`n`n" . t("Copied, Press [CLX+Space] to hide.") Clipboard := brainstormStagedAnswer @@ -212,3 +331,136 @@ brainstorm_EncodeDecodeURI(str, encode := true, component := true) } Return JS[ (encode ? "en" : "de") . "codeURI" . (component ? "Component" : "") ](str) } + +; https://www.autohotkey.com/boards/viewtopic.php?t=67426 dl +CreateFormData(ByRef retData, ByRef retHeader, objParam) { + New CreateFormData(retData, retHeader, objParam) +} + +Class CreateFormData { + + __New(ByRef retData, ByRef retHeader, objParam) { + + Local CRLF := "`r`n", i, k, v, str, pvData + ; Create a random Boundary + Local Boundary := this.RandomBoundary() + Local BoundaryLine := "------------------------------" . Boundary + + this.Len := 0 ; GMEM_ZEROINIT|GMEM_FIXED = 0x40 + this.Ptr := DllCall( "GlobalAlloc", "UInt",0x40, "UInt",1, "Ptr" ) ; allocate global memory + + ; Loop input paramters + For k, v in objParam + { + If IsObject(v) { + For i, FileName in v + { + str := BoundaryLine . CRLF + . "Content-Disposition: form-data; name=""" . k . """; filename=""" . FileName . """" . CRLF + . "Content-Type: " . this.MimeType(FileName) . CRLF . CRLF + this.StrPutUTF8( str ) + this.LoadFromFile( Filename ) + this.StrPutUTF8( CRLF ) + } + } Else { + str := BoundaryLine . CRLF + . "Content-Disposition: form-data; name=""" . k """" . CRLF . CRLF + . v . CRLF + this.StrPutUTF8( str ) + } + } + + this.StrPutUTF8( BoundaryLine . "--" . CRLF ) + + ; Create a bytearray and copy data in to it. + retData := ComObjArray( 0x11, this.Len ) ; Create SAFEARRAY = VT_ARRAY|VT_UI1 + pvData := NumGet( ComObjValue( retData ) + 8 + A_PtrSize ) + DllCall( "RtlMoveMemory", "Ptr",pvData, "Ptr",this.Ptr, "Ptr",this.Len ) + + this.Ptr := DllCall( "GlobalFree", "Ptr",this.Ptr, "Ptr" ) ; free global memory + + retHeader := "multipart/form-data; boundary=----------------------------" . Boundary + } + + StrPutUTF8( str ) { + Local ReqSz := StrPut( str, "utf-8" ) - 1 + this.Len += ReqSz ; GMEM_ZEROINIT|GMEM_MOVEABLE = 0x42 + this.Ptr := DllCall( "GlobalReAlloc", "Ptr",this.Ptr, "UInt",this.len + 1, "UInt", 0x42 ) + StrPut( str, this.Ptr + this.len - ReqSz, ReqSz, "utf-8" ) + } + + LoadFromFile( Filename ) { + Local objFile := FileOpen( FileName, "r" ) + this.Len += objFile.Length ; GMEM_ZEROINIT|GMEM_MOVEABLE = 0x42 + this.Ptr := DllCall( "GlobalReAlloc", "Ptr",this.Ptr, "UInt",this.len, "UInt", 0x42 ) + objFile.RawRead( this.Ptr + this.Len - objFile.length, objFile.length ) + objFile.Close() + } + + RandomBoundary() { + str := "0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z" + Sort, str, D| Random + str := StrReplace(str, "|") + Return SubStr(str, 1, 12) + } + + MimeType(FileName) { + n := FileOpen(FileName, "r").ReadUInt() + Return (n = 0x474E5089) ? "image/png" + : (n = 0x38464947) ? "image/gif" + : (n&0xFFFF = 0x4D42 ) ? "image/bmp" + : (n&0xFFFF = 0xD8FF ) ? "image/jpeg" + : (n&0xFFFF = 0x4949 ) ? "image/tiff" + : (n&0xFFFF = 0x4D4D ) ? "image/tiff" + : "application/octet-stream" + } + +} + +; Save clipboard image to file +save_clipboard_image() { + global brainstormFilePath + If (brainstormClipType = "" || brainstormClipType = NONTEXT := 2) { + FileRecycle % brainstormFilePath + clipboardToImageFile(brainstormFilePath) + If FileExist(brainstormFilePath){ + ; preview image + ; Run % brainstormFilePath + return brainstormFilePath + } + ; silent fail + } + ; silent fail + Return "" +} + +save_active_window_image() { + global brainstormFilePath + FileRecycle % brainstormFilePath + activeWindowToImageFile(brainstormFilePath) + If FileExist(brainstormFilePath){ + ; preview image + ; Run % brainstormFilePath + return brainstormFilePath + } + ; silent fail + Return "" +} + +clipboardToImageFile(filePath) { + pToken := Gdip_Startup() + pBitmap := Gdip_CreateBitmapFromClipboard() ; Clipboard -> bitmap + Gdip_SaveBitmapToFile(pBitmap, filePath) ; Bitmap -> file + Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken) +} +activeWindowToImageFile(filePath) { + pToken := Gdip_Startup() + WinGetPos, x, y, w, h, A + pBitmap := Gdip_BitmapFromScreen(x "|" y "|" w "|" h) ; Screen -> bitmap + Gdip_SaveBitmapToFile(pBitmap, filePath) ; Bitmap -> file + Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken) +} + +clipChanged(type) { + brainstormClipType := type +} diff --git a/Modules/CLX-Settings.ahk b/Modules/CLX-Settings.ahk index 799a90b..036c4ff 100644 --- a/Modules/CLX-Settings.ahk +++ b/Modules/CLX-Settings.ahk @@ -24,11 +24,15 @@ CLX_Exit() { ExitApp } + ; 修改配置 + #if CapsLockXMode -;, :: 配置文件编辑() -,:: CLX_ConfigWindow() + ;, :: 配置文件编辑() + ,:: CLX_ConfigWindow() + +#if CLX_ConfigWindow() { @@ -99,7 +103,7 @@ Button重新載入: return CLX_ConfigureUpdate: global T_TomatoLife - global T_XKeyAsCapsLock + global T_XKeyAsCapsLock global T_XKeyAsSpace global T_AskRunAsAdmin global CLX_CONFIG_ONSTARTUP diff --git a/Modules/TomatoLife.ahk b/Modules/TomatoLife.ahk index 62b9a27..ebc025b 100644 --- a/Modules/TomatoLife.ahk +++ b/Modules/TomatoLife.ahk @@ -16,10 +16,13 @@ if (T_TomatoLife) { 高精度时间配置() GoSub CLX_番茄时钟定时任务 ; [有一个难以复现的 bug・Issue #17・snolab/CapsLockX]( https://github.com/snolab/CapsLockX/issues/17 ) + ; 番茄报时() } Return +^!i:: 番茄报时() + 高精度时间配置(){ ; global T_TomatoLife := CLX_Config("TomatoLife", "", 0, "使用定时任务") ; MsgBox, 你开启了定时任务,是否现在配置高精度时间? @@ -50,7 +53,8 @@ Return ; CapsLockX 暂停时,番茄状态也暂停 if (CLX_Paused) Return - ; tooltip 检测睡眠标记文件以跳过报时 + + ; tooltip skip if sleep static SLEEPING_FLAG_CLEAN := 0 if(!SLEEPING_FLAG_CLEAN) { ; 启动时重置标记文件 @@ -62,6 +66,11 @@ Return Return } } + ; skip if afk + isAfk := A_TimeIdlePhysical > 5 * 60 * 1000 ; 5min + if(isAfk){ + Return + } 番茄状态 := 番茄状态计算() ; tooltip 边沿触发过滤器 @@ -80,22 +89,24 @@ Return Return } 上次番茄状态 := 番茄状态 - MsgBox, 番茄:%番茄状态% + ; MsgBox, 番茄:%番茄状态% ; 状态动作 if ("工作时间" == 番茄状态) { TrayTip % t("番茄时钟:") . %番茄状态%, % t("工作时间到啦!") SoundPlay % "Data/NoteC_G.mp3" ; 升调 - ; sleep 10000 ; 暂缓10秒切工作桌面 - if (T_TomatoLife_UseTomatoLifeSwitchVirtualDesktop && !tomatoLaunchFlag) { + ; sleep 10000 ; 暂缓10秒切桌面 + ; && !tomatoLaunchFlag + if (T_TomatoLife_UseTomatoLifeSwitchVirtualDesktop) { Func("SwitchToDesktop").Call(2) ; 切到工作桌面(桌面2) } } if ("休息时间" == 番茄状态) { TrayTip % t("番茄时钟:") . %番茄状态%, % t("起来运动一下收拾收拾东西!") SoundPlay % "Data/NoteG_C.mp3" ; 降调 - sleep 10000 ; 暂缓10秒切休息桌面 - if(T_TomatoLife_UseTomatoLifeSwitchVirtualDesktop && !tomatoLaunchFlag) { + ; sleep 10000 ; 暂缓10秒切桌面 + ; && !tomatoLaunchFlag + if(T_TomatoLife_UseTomatoLifeSwitchVirtualDesktop) { Func("SwitchToDesktop").Call(1) ; 切到休息桌面(桌面1) } } @@ -110,7 +121,7 @@ UnixTimeGet() } CLX_番茄时钟定时任务: - if (T_TomatoLife && T_TomatoLife_UseTomatoLife) + if (T_TomatoLife) 番茄报时() ; 下次循环时间计算 间隔 := 60000 ; 间隔为1分钟,精度到毫秒级