StrokesPlus.net脚本持续更新

划词翻译 v0.2

划词后,中文Google翻译,英文句子Google翻译,英文单词有道翻译,结果保存剪切板,同时显示在鼠标处

自动6秒关闭结果显示,鼠标点击和滚动关闭显示需要在鼠标事件中设置(见下方)

由于是使用自带的sp.DisplayText显示结果,需要截取结果,当前长句中英、英中翻译结果换行是根据长度截取,效果不好,暂时没有更好的显示办法,如果使用其他显示,需要调整,不影响直接从剪切板粘贴

sp.Sleep(400);
sp.SendModifiedVKeys([vk.LCONTROL], [vk.VK_C]);
sp.Sleep(100);
var text = clip.GetText();
text = text.replace('\r\n', '');
var r={
    "wd":0,//中英文字数
    "nwd":0,//英数词数
    "nb":0,//数字词数
    "c":0,//字符数
    "cb":0,//非空格字符
    "r":0,//回车
    "en":0,//英文字母数
    "cn":0,//中文字数
    "bl":0//非回车空格
};
var words = text.match(/\w+([’\']\w+)?/g)||[];//含撇号(如I'm)的单词视为一个词
var cnwords = text.match(/[\u4e00-\u9fa5]/g)||[];//统一中文字范围
r.nwd = words.length;
r.cn = cnwords.length;


var httpHandler = new HttpClientHandler();
httpHandler.AutomaticDecompression = host.flags(DecompressionMethods.GZip, DecompressionMethods.Deflate);
var client = new HttpClient(httpHandler);

var response;
var result;
var strTrans = '';
var json;

if(r.cn > 0) {
    client.BaseAddress = new Uri("https://translate.googleapis.com/translate_a/");
    response = client.GetAsync("single?client=gtx&sl=zh-CN&tl=en&dt=t&q=" + text).Result;
    result = response.Content.ReadAsStringAsync().Result;
    json = JSON.parse(result);
    for (var i = 0; i < json[0].length; i++) {
        strTrans += json[0][i][0];
    }

    clip.SetText(strTrans);
    strTrans = strTrans.replace(/(\S+\s*){1,10}/g, "$&\n").trim();
} else if(r.nwd > 1) {
    client.BaseAddress = new Uri("https://translate.googleapis.com/translate_a/");
    response = client.GetAsync("single?client=gtx&sl=auto&tl=zh-CN&dt=t&q=" + text).Result;
    result = response.Content.ReadAsStringAsync().Result;
    json = JSON.parse(result);
    for (var i = 0; i < json[0].length; i++) {
        strTrans += json[0][i][0];
    }
    clip.SetText(strTrans);
    if(strTrans.length < 25) {
        strTrans = strTrans;
    } else if(strTrans.length > 25 && strTrans.length <= 50) {
        strTrans = strTrans.slice(0, 25) + '\r\n' +
                                strTrans.slice(25, 50);
    } else if(strTrans.length > 50 && strTrans.length <= 75) {
        strTrans = strTrans.slice(0, 25) + '\r\n' +
                                strTrans.slice(25, 50) + '\r\n' +
                                strTrans.slice(50, 75);
    } else if(strTrans.length > 75 && strTrans.length <= 100) {
        strTrans = strTrans.slice(0, 25) + '\r\n' +
                                strTrans.slice(25, 50) + '\r\n' +
                                strTrans.slice(50, 75) + '\r\n' +
                                strTrans.slice(75, 100);
    } else if(strTrans.length > 100 && strTrans.length <= 125) {
        strTrans = strTrans.slice(0, 25) + '\r\n' +
                                strTrans.slice(25, 50) + '\r\n' +
                                strTrans.slice(50, 75) + '\r\n' +
                                strTrans.slice(75, 100) + '\r\n' +
                                strTrans.slice(100, 125);
    } else if(strTrans.length > 125 && strTrans.length <= 150) {
        strTrans = strTrans.slice(0, 25) + '\r\n' +
                                strTrans.slice(25, 50) + '\r\n' +
                                strTrans.slice(50, 75) + '\r\n' +
                                strTrans.slice(75, 100) + '\r\n' +
                                strTrans.slice(100, 125) + '\r\n' +
                                strTrans.slice(125, 150);
    } else if(strTrans.length > 150) {
        strTrans = strTrans.slice(0, 25) + '\r\n' +
                                strTrans.slice(25, 50) + '\r\n' +
                                strTrans.slice(50, 75) + '\r\n' +
                                strTrans.slice(75, 100) + '\r\n' +
                                strTrans.slice(100, 125) + '\r\n' +
                                strTrans.slice(125, 150) + '\r\n' +
                                strTrans.slice(150, 175);
    }


} else if(r.nwd = 1) {
    client.BaseAddress = new Uri("https://dict.youdao.com/");
    response = client.GetAsync("jsonapi?xmlVersion=5.1&jsonversion=2&q=" + text).Result;
    result = response.Content.ReadAsStringAsync().Result;
    json = JSON.parse(result);

    var arr = json.ec.word[0].trs
    for(i = 0; i < arr.length; i++) {
        if(i < arr.length -1) {
            if(arr[i].tr[0].l.i[0].length < 25) {
                strTrans = strTrans + arr[i].tr[0].l.i[0].slice(0, 25) + '\r\n';
            } else if(arr[i].tr[0].l.i[0].length > 25 && arr[i].tr[0].l.i[0].length < 50) {
                strTrans = strTrans + arr[i].tr[0].l.i[0].slice(0, 25) + '\r\n' +
                                        arr[i].tr[0].l.i[0].slice(25, 50) + '\r\n';
            } else if(arr[i].tr[0].l.i[0].length > 50 && arr[i].tr[0].l.i[0].length < 75) {
                strTrans = strTrans + arr[i].tr[0].l.i[0].slice(0, 25) + '\r\n' +
                                        arr[i].tr[0].l.i[0].slice(25, 50) + '\r\n' +
                                        arr[i].tr[0].l.i[0].slice(50, 75) + '\r\n';
            } else if(arr[i].tr[0].l.i[0].length > 75) {
                strTrans = strTrans + arr[i].tr[0].l.i[0].slice(0, 25) + '\r\n' +
                                        arr[i].tr[0].l.i[0].slice(25, 50) + '\r\n' +
                                        arr[i].tr[0].l.i[0].slice(50, 75) + '\r\n' +
                                        arr[i].tr[0].l.i[0].slice(75, 100) + '\r\n';
            }
        } else {
            if(arr[i].tr[0].l.i[0].length < 25) {
                strTrans = strTrans + arr[i].tr[0].l.i[0].slice(0, 25);
            } else if(arr[i].tr[0].l.i[0].length > 25 && arr[i].tr[0].l.i[0].length < 50) {
                strTrans = strTrans + arr[i].tr[0].l.i[0].slice(0, 25) + '\r\n' +
                                        arr[i].tr[0].l.i[0].slice(25, 50);
            } else if(arr[i].tr[0].l.i[0].length > 50 && arr[i].tr[0].l.i[0].length < 75) {
                strTrans = strTrans + arr[i].tr[0].l.i[0].slice(0, 25) + '\r\n' +
                                        arr[i].tr[0].l.i[0].slice(25, 50) + '\r\n' +
                                        arr[i].tr[0].l.i[0].slice(50, 75);
            } else if(arr[i].tr[0].l.i[0].length > 75) {
                strTrans = strTrans + arr[i].tr[0].l.i[0].slice(0, 25) + '\r\n' +
                                        arr[i].tr[0].l.i[0].slice(25, 50) + '\r\n' +
                                        arr[i].tr[0].l.i[0].slice(50, 75) + '\r\n' +
                                        arr[i].tr[0].l.i[0].slice(75, 100);
            }
        }
    }
}

//StrokesPlus.Console.Log(strTrans);
if(strTrans != null) {
    sp.StoreString('strTrans', strTrans);
}

sp.StoreBool("Trans", true);
sp.CreateTimer('Trans', 6000, -1, String.raw`sp.StoreBool("Trans", false);sp.DeleteTimer('Trans');`);      

httpHandler.Dispose();
client.Dispose();
response.Dispose();


第二部分

添加到全局动作-启动/退出

重要:如果已经添加过DisplayTextInfo计时器,直接复制添加 var currentMouseLocation} 之间的代码(即开始结束之间)

sp.CreateTimer("LangWatch",
               250,
               250,
               `var info = new DisplayTextInfo();
                 
               info.TitleFont = new Font('Segoe UI', 12, host.flags(FontStyle.Bold));
               info.MessageFont = new Font("Segoe UI Semibold", 12);
               info.BackColor = "15,179,98";  //绿
               info.ForeColor = "255,255,255";
               info.Duration = 1000;
               info.Opacity = 0.5; //透明度
               info.Location = "190,809"; //翻译结果显示坐标,相对于屏幕分辨率,当前是屏幕左下角
               //info.Location = "bottom";
               info.FadeSteps = 10;
               info.Padding = 10;
               info.Message = "";

                //开始
              var currentMouseLocation = sp.GetCurrentMousePoint();
              var currpt = sp.GetStoredPoint("mouseClick"); 
              if(sp.GetStoredBool("Trans")) {
                        info.Opacity = 0.6;
                        info.Padding = 5;   
                        info.MessageAlignment = 'Left';
                        info.MessageFont = new Font("Segoe UI Semibold", 8); //结果字体大小,13寸屏幕检验8/10,大于13寸建议12/14
                        //info.Location = (currpt.X + 10) + ',' + (currpt.Y + 35); //鼠标点击位置,需要在鼠标左键点击脚本中添加 var currentMouseLocation = sp.GetCurrentMousePoint(); sp.StorePoint("mouseClick", currentMouseLocation);
                        info.Location = (currentMouseLocation.X + 10) + ',' + (currentMouseLocation.Y + 35); //鼠标位置
                        info.BackColor = "245,245,245"; 
                        info.ForeColor = 'black';
                        //info.Duration = 3000;
                        //info.Message = clip.GetText();
                        //info.Message = sp.GetSavedString('strTrans');
                        info.Message = sp.GetStoredString('strTrans');
                   }
                //结束

                if(info.Message.length > 0) {
                    if(sp.GetStoredBool("LangShown")) {
                        sp.DisplayTextUpdate(info);
                    } else {
                        sp.DisplayText(info);
                        sp.StoreBool("LangShown", true);
                    }
                } else {
                    //sp.DisplayTextClose();
                    sp.StoreBool("LangShown", false);
                }
               `
);

左键点击关闭

添加到鼠标事件-左键单击 sp.DeleteStoredString('strTrans');

鼠标滚轮关闭

添加到鼠标事件-鼠标滚轮最下方else里面sp.DeleteStoredString('strTrans');

选中图片上传返回链接(ShareX)

  1. 在ShareX-快捷键-创建一条任务-命名为Upload to vgy
    选择需要上传的的图床
  2. 添加代码到手势
    actionName是1中的任务的命名

返回链接需要等1-2s,之后要是进行图片搜索,可以使用图片搜索引擎(ShareX中自带Google图片搜索)

var wndHandle = sp.ForegroundWindow().HWnd;
var desktopHandle = sp.DesktopWindowListView().HWnd;
var result = 1;
var selectedFiles;
var fullPath = "";
var isDesktop = false;
var success = false;
var actionName = "Upload to vgy"

if(wndHandle.ToInt32() == desktopHandle.ToInt32() || sp.LastFocusControl().HWnd.ToInt32() == desktopHandle.ToInt32()) {
    //Desktop
    selectedFiles = sp.GetSelectedFilesOnDesktop();
    isDesktop = true;
} else {
    //Not Desktop
    selectedFiles = sp.GetSelectedFilesInExplorer(wndHandle);
}

if(selectedFiles.Length != 0) {
    fullPath = selectedFiles[0];

    if(isDesktop) {
        fullPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + "\\" + fullPath;
    }

    result = sp.RunProgram('D:\\Program Files\\ShareX\\ShareX.exe', 
                               `"${fullPath}" -task "${actionName}"`,
                               'open', 'hidden', false, true, true);


    if(result == 0) { 
        success = true;
        sp.ShowBalloonTip("OK", "", "info", 1000);
    } 
} 

if(!success) {
    sp.ShowBalloonTip("Upload to Imgur", "Failed", "error", 1000);
}
//sp.Sleep(2000);

选中图片打开编辑(ShareX)

var wndHandle = sp.ForegroundWindow().HWnd;
var desktopHandle = sp.DesktopWindowListView().HWnd;
var result = 1;
var selectedFiles;
var fullPath = "";
var isDesktop = false;
var success = false;

if(wndHandle.ToInt32() == desktopHandle.ToInt32() || sp.LastFocusControl().HWnd.ToInt32() == desktopHandle.ToInt32()) {
    //Desktop
    selectedFiles = sp.GetSelectedFilesOnDesktop();
    isDesktop = true;
} else {
    //Not Desktop
    selectedFiles = sp.GetSelectedFilesInExplorer(wndHandle);
}

if(selectedFiles.Length != 0) {
    fullPath = selectedFiles[0];

    if(isDesktop) {
        fullPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + "\\" + fullPath;
    }

    result = sp.RunProgram('D:\\Program Files\\ShareX\\ShareX.exe', 
                               `-imageeditor "${fullPath}"`,
                               'open', 'hidden', false, true, true);


    if(result == 0) { 
        success = true;
    } 
} 

if(!success) {
    sp.ShowBalloonTip("edit", "Failed", "error", 1000);
}

Alt+拖动窗口

也就是AltDrag,按下Alt,鼠标在窗口任意位置点击后,可以拖动窗口,Win10测试正常(官方论坛帖子

添加到:全局动作- 鼠标事件- 左键单击

if(click.Down) {
    if((sp.GetKeyState(vk.LMENU) & 0x8000) && !sp.GetStoredBool("MoveWindowActive")) {
        if(!click.Window.Maximized) {
            sp.StoreBool("MoveWindowActive", true);
            sp.StoreHandle("MoveWindowHandle", click.Window.HWnd);
            sp.StorePoint("MoveWindowMouseStart", sp.GetCurrentMousePoint());
            sp.StorePoint("MoveWindowStart", click.Window.Location);
            sp.CreateTimer("MoveWindow", 20, 10, String.raw`
                                    var wnd = sp.WindowFromHandle(sp.GetStoredHandle("MoveWindowHandle"));
                                    if(sp.GetKeyState(vk.ESCAPE) & 0x8000) {
                                        wnd.Location = sp.GetStoredPoint("MoveWindowStart");
                                        sp.DeleteTimer("MoveWindow");
                                    }
                                    var startMousePt = sp.GetStoredPoint("MoveWindowMouseStart");
                                    var currMousePt = sp.GetCurrentMousePoint();
                                    var currWinPt = wnd.Location;
                                    if(sp.GetStoredBool("MoveWindowActive")) {
                                        wnd.Location = new Point(currWinPt.X + currMousePt.X - startMousePt.X, currWinPt.Y + currMousePt.Y - startMousePt.Y);
                                    }
                                    sp.StorePoint("MoveWindowMouseStart", currMousePt);
                                `);
        }
    }
} else {
    if(sp.GetStoredBool("MoveWindowActive"))
    {
        sp.DeleteStoredHandle("MoveWindowHandle");
        sp.DeleteStoredBool("MoveWindowActive");
        sp.DeleteTimer("MoveWindow");
        sp.DeleteStoredPoint("MoveWindowMouseStart");
        sp.DeleteStoredPoint("MoveWindowStart");
    }
}

搜索选中文字或打开链接

选中是的链接会直接浏览器打开,非链接会百度搜索(此代码为zzm.note分享卡饭)

sp.SendModifiedVKeys([vk.LCONTROL], [vk.VK_C]);
sp.Sleep(50);
s=clip.GetText();
keyword = s.trim();
var n = /^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/i;
var match = n.exec(keyword);
if(match != null) {
    if(keyword.substr(0, 4) == 'http'){
        sp.RunProgram(keyword, '', 'open', 'normal', true, false, false);
    }else{
        sp.RunProgram('https://'+keyword, '', 'open', 'normal', true, false, false);
    }
}else{
    sp.RunProgram('https://www.baidu.com/s?wd='+keyword+'&ie=utf-8', '', 'open', 'normal', true, false, false);//目前没有默认参数,所以不能省略.
}

屏幕取色

var currpt = sp.GetCurrentMousePoint();
var pxcolor = sp.GetPixelColorFromPoint(currpt);
var info = new DisplayTextInfo();
info.Message = "x: "+currpt.X+" y: " + currpt.Y+"\nRGB: "+pxcolor.R+"."+pxcolor.G+"."+pxcolor.B;
info.Duration = 1000;
info.MessageAlignment = "left";
info.Location = (currpt.X+10)+','+(currpt.Y-100); 
info.MessageFont = new Font("Segoe UI Semibold", 12);
info.BackColor = "black";
info.Padding = 0;
info.ClipToWorkingArea = false;
sp.DisplayText(info);
var chex = "";
while (!(sp.GetKeyState(vk.LBUTTON) & 0x8000)) {  
    currpt = sp.GetCurrentMousePoint();
    pxcolor = sp.GetPixelColorFromPoint(currpt);
    pxcolorAbove = sp.GetPixelColorFromPoint(new Point(currpt.X, currpt.Y - 100));
    var rhex = Number(pxcolor.R).toString(16);
    if (rhex.length < 2) {
         rhex = "0" + rhex;
    };
    var ghex = Number(pxcolor.G).toString(16);
    if (ghex.length < 2) {
         ghex = "0" + ghex;
    };
    var bhex = Number(pxcolor.B).toString(16);
    if (bhex.length < 2) {
         bhex = "0" + bhex;
    };
    var rhexAbove = Number(pxcolorAbove.R).toString(16);
    if (rhexAbove.length < 2) {
         rhexAbove = "0" + rhexAbove;
    };
    var ghexAbove = Number(pxcolorAbove.G).toString(16);
    if (ghexAbove.length < 2) {
         ghexAbove = "0" + ghex;
    };
    var bhexAbove = Number(pxcolorAbove.B).toString(16);
    if (bhexAbove.length < 2) {
         bhexAbove = "0" + bhex;
    };
    //chex = "#" + rhex + ghex + bhex;
    chex = pxcolor.R+","+pxcolor.G+","+pxcolor.B;
    info.Message = "x: "+currpt.X+" y: " + currpt.Y;
    info.Message += "\nAt Cursor - RGB: "+pxcolor.R+","+pxcolor.G+","+pxcolor.B;
    //info.Message += "\nAt Cursor - hex: " + chex
    //info.Message += "\nAbove (100px) - RGB: "+pxcolorAbove.R+","+pxcolorAbove.G+","+pxcolorAbove.B; 
    //info.Message += "\nAbove (100px) - hex: #" + rhex + ghex + bhex; 
    info.Location = (currpt.X+10)+','+(currpt.Y-100); 
    sp.DisplayTextUpdate(info); //Refresh the existing text and location, instead of closing and reopening the popup
    sp.Sleep(10);
}
clip.SetText(chex);
sp.DisplayTextClose();

当前窗口信息

显示窗口程序名,标题,类,句柄等,点确定,选中条目结果复制到剪切板

// VARIABLES
    var w_exe = sp.ForegroundWindow().Process.ProcessName;
    var w_title = sp.ForegroundWindow().Title;
    var w_class = sp.ForegroundWindow().ClassName;
    var w_HWnd = sp.ForegroundWindow().HWnd.ToString();
    //var w_handle = action.Window.Process.Handle.ToString();
    var w_id = sp.ForegroundWindow().Process.Id;

// TITLES
    var txt_exe = "Exe:       ";
    var txt_title = "Title:      ";
    var txt_class = "Class:     ";
    var txt_HWnd = "HWnd:   ";
    var txt_id = "Id:          ";

// INPUT BOX
    var inputBoxInfo = new InputBoxInfo();
    inputBoxInfo.Title = "Window Info";
    inputBoxInfo.Message = "Choose parameters:";

// ITEMS
    inputBoxInfo.Items.Add(txt_exe+w_exe);
    inputBoxInfo.Items.Add(txt_title+w_title);
    inputBoxInfo.Items.Add(txt_class+w_class);
    inputBoxInfo.Items.Add(txt_HWnd+w_HWnd);
    inputBoxInfo.Items.Add(txt_id+w_id);

// SELECT ITEM AND COPY TO CLIP
    inputBoxInfo.SelectedValue = txt_exe+w_exe;
    var res = sp.InputBox(inputBoxInfo);
    if(res != null)
    {
        if(res.startsWith(txt_exe) == true)                res = w_exe;
        else if(res.startsWith(txt_title) == true)     res = w_title;
        else if(res.startsWith(txt_class) == true)     res = w_class;
        else if(res.startsWith(txt_HWnd) == true)       res = w_HWnd;
        else if(res.startsWith(txt_id) == true)          res = w_id + ""; // simple conversion into a string by adding an empty string
        clip.SetText(res)
    }

选中图片转化base64

结果复制到剪切板

var wndHandle = sp.ForegroundWindow().HWnd;
var desktopHandle = sp.DesktopWindowListView().HWnd;
var selectedFiles;
var fullPath = "";
var isDesktop = false;

if(wndHandle.ToInt32() == desktopHandle.ToInt32() || sp.LastFocusControl().HWnd.ToInt32() == desktopHandle.ToInt32()) {
    //Desktop
    selectedFiles = sp.GetSelectedFilesOnDesktop();
    isDesktop = true;
} else {
    //Not Desktop
    selectedFiles = sp.GetSelectedFilesInExplorer(wndHandle);
}

if(selectedFiles.Length != 0) {
    fullPath = selectedFiles[0];

    if(isDesktop) {
        fullPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + "\\" + fullPath;
    }


        var base64Img = clr.System.Convert.ToBase64String(clr.System.IO.File.ReadAllBytes(fullPath));
		var imgHTML = "data:image/png;base64," + base64Img;
		clip.SetText(imgHTML);
} 

固定鼠标在屏幕的当前点

用于鼠标1分钟未移动,鼠标固定,为了避免鼠标误移动到角落执行动作

添加2代码到全局动作-启动/退出

左键点击解除固定:
添加1代码到:全局动作-鼠标事件-左键单击

1

sp.MouseRestrictClear();
sp.StoreBool("mouseRestrict", false);

2

sp.CreateTimer("Location", 
                        0, 
                        1000, 
                        `var currentMouseCursor = sp.GetCurrentMouseCursor();

                        var startPoint = sp.GetStoredPoint("mouseStart"); 
                        //Get the current mouse location
                        var currPoint = sp.GetCurrentMousePoint();
                        //var devices = sp.AllDevices();
                        if(!sp.GetStoredBool("mouseRestrict")) {
                            //Get the start point/location
                            if(currPoint.X - startPoint.X === 0 && currPoint.X != 0 && currPoint.Y != 0) {
                                sp.StoreNumber('n', sp.GetStoredNumber('n') + 1);
                                var num = sp.GetStoredNumber('n');
                                if(num === 60) {
                                    sp.MouseRestrictToRectangle(new Rectangle(currPoint.X, currPoint.Y, 0, 0));
                                    sp.StoreBool("mouseRestrict", true);
                                }

                            } else {
                                currentMouseLocation = sp.GetCurrentMousePoint();
                                sp.StorePoint("mouseStart", currentMouseLocation);
                                sp.StoreNumber('n', 0);
                            }

                        } else {
                            sp.StoreNumber('n', 0);
                        }`

); 

右键执行中键

点右键关闭浏览器标签页,打开书签栏书签,支持Chrome,Edge,Firefox,按Ctrl+右键正常显示菜单(官方论坛帖子

添加到全局动作-启动/退出

重要设置:选项-高级-启动订阅鼠标钩子事件

// Define globally instead of each click
var browser_classname = ["Chrome_WidgetWin_1", "MozillaWindowClass"];

var mouseButtonEventObj = sp.GetStoredObject("mouseButtonEvent");
//Disconnect any existing binding for this object name
if(mouseButtonEventObj.GetType().FullName.includes('EventConnection'))
{
    mouseButtonEventObj.disconnect();
    sp.DeleteStoredObject("mouseButtonEvent");
} 

//Create the event binding and bind to synchronous event
var mouseButtonEvent = MouseHook.OnMouseHookButtonEvent.connect(
    function (sender, mouseHookEvent) {
        //Wrap all code in try/catch, exceptions will crash S+
        try
        {
            if(mouseHookEvent.Button == MouseButtons.Right)
            {
                var mouseWindow = sp.WindowFromPoint(mouseHookEvent.Location, true);
                if(browser_classname.includes(mouseWindow.ClassName) 
                    && ((mouseHookEvent.Location.Y >= mouseWindow.Rectangle.Top && mouseHookEvent.Location.Y < mouseWindow.Rectangle.Top + 35) || (mouseHookEvent.Location.Y >= mouseWindow.Rectangle.Top + 70 && mouseHookEvent.Location.Y < mouseWindow.Rectangle.Top + 105))
                    && !mouseHookEvent.InjectedByHost) 
                {
                    if(mouseHookEvent.ButtonState == ButtonState.Up)
                    {
                        if (sp.GetKeyState(vk.CONTROL) & 0x8000)
                        {
                            // Invoke right click on new thread so the hook
                            // doesn't get stuck while waiting for this method 
                            // to return
                            sp.CreateTimer("rightClick", 
                                           0, 
                                           -1, 
                                           `sp.MouseClick(sp.GetCurrentMousePoint(), MouseButtons.Right, true, true); 
                                            sp.DeleteTimer("rightClick");`
                                          );
                            
                        }
                        else
                        {
                            // Invoke middle click on new thread so the hook
                            // doesn't get stuck while waiting for this method 
                            // to return
                            sp.CreateTimer("middleClick", 
                                           0, 
                                           -1, 
                                           `sp.MouseClick(sp.GetCurrentMousePoint(), MouseButtons.Middle, true, true); 
                                            sp.DeleteTimer("middleClick");`
                                          );
                        }
                    }
                    mouseHookEvent.Consume = true;
                }
            }
        }
        catch(err) 
        {
            StrokesPlus.Console.Log(err.message);
        }
    });

//Note that on S+ reload, events in Stored Object list have disconnect called on them
sp.StoreObject("mouseButtonEvent", mouseButtonEvent);

窗口透明(鼠标可点击)

执行后鼠标所在窗口透明,且置顶,鼠标可点击后方窗口,再次执行后恢复

不足之处,只能一次设置一个窗口透明以及鼠标穿透,然后恢复,不设置鼠标穿透,可以同时设置多个窗口透明

参照 See Through Windows – 透过窗口看窗口 (当前该软件功能正常)

添加到全局动作-启动/退出

if(!NativeModules.User32)
{
    var IntPtrT = host.typeOf(clr.System.IntPtr);
    var Int32T = host.typeOf(clr.System.Int32);
	
    var user32TB = sp.NativeModule().DefineType("User32", "Class,Public,SequentialLayout,Serializable");

    user32TB.DefinePInvokeMethod("GetWindowLong",
								 "user32.dll",
								 [IntPtrT,Int32T], 
								 Int32T, 
								 "PreserveSig");

    user32TB.DefinePInvokeMethod("SetWindowLong",
								 "user32.dll",
								 [IntPtrT,Int32T,Int32T], 
								 Int32T, 
								 "PreserveSig");

	user32TB.Create();
}

执行动作

var WS_EX_LAYERED = 0x80000;
var WS_EX_TRANSPARENT = 0x20;
var GWL_EXSTYLE = (-20);

if(sp.GetStoredObject('WinTrans').Alpha == 128){
    var hWnds = sp.GetStoredObject('WinTrans').HWnd;
    sp.GetStoredObject('WinTrans').Alpha = 255;  //Remove transparency
    sp.GetStoredObject('WinTrans').TopMost = false;
    //Which will disable the Preview Pciture Window activate
    /*if(sp.GetStoredObject('WinTrans').ClassName != 'WindowsForms10.Window.8.app.0.13965fa_r6_ad1') {
        sp.GetStoredObject('WinTrans').Activate();
    }*/
    NativeModules.User32.SetWindowLong(hWnds ,GWL_EXSTYLE, NativeModules.User32.GetWindowLong(hWnds, GWL_EXSTYLE) & (~WS_EX_TRANSPARENT));
    sp.DeleteStoredObject('WinTrans');
} else {
    var hWnd = sp.WindowFromPoint(sp.GetCurrentMousePoint(), true).HWnd;
    sp.WindowFromPoint(sp.GetCurrentMousePoint(), true).Alpha = 128;  //Make 50% transparent
    sp.WindowFromPoint(sp.GetCurrentMousePoint(), true).TopMost = true;
    sp.StoreObject('WinTrans', sp.WindowFromPoint(sp.GetCurrentMousePoint(), true));
    NativeModules.User32.GetWindowLong(hWnd, GWL_EXSTYLE);
    NativeModules.User32.SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_TRANSPARENT | WS_EX_LAYERED);
}

屏幕边缘滚动调节亮度、声音、浏览器标签页切换、程序切换

屏幕左边缘调节亮度,任务栏调节声音,屏幕右边缘切换程序,浏览器标签栏切换

默认设置滚动距离屏幕左右边缘20和25px

添加到全局动作-鼠标事件-鼠标滚轮 需要勾选启动和吞掉

重要:注释默认代码备份

下载亮度插件https://www.strokesplus.net/files/ScreenBrightness.dll

插件-添加插件

插件会自动复制到S+安装文件夹,不需要手动复制过去,另外此插件调节亮度时不会显示亮度条状态,如果需要亮度条可以配合一款软件快捷键调节(因为无法识别键盘Fn)

var mouseLocation = sp.GetCurrentMousePoint();
var currentScreen = Screen.FromPoint(mouseLocation);
if(mouseLocation.Y >= currentScreen.Bounds.Bottom - 40) {
    //Mouse is at edge of screen
    if(wheel.Delta > 0) {
        sp.SendVKey(vk.VOLUME_UP);
    } else {
        sp.SendVKey(vk.VOLUME_DOWN);
    }
} else if(mouseLocation.Y <= currentScreen.Bounds.Top + 35) {
   if(wheel.Window.Process.MainModule.ModuleName == "chrome.exe" || wheel.Window.Process.MainModule.ModuleName == "msedge.exe" ||
        wheel.Window.Process.MainModule.ModuleName == "MicrosoftEdge.exe" || wheel.Window.Process.MainModule.ModuleName == "Firefox.exe") {
       if(wheel.Delta > 0) {
            //mouse wheel scrolled up
            sp.SendModifiedVKeys([vk.LCONTROL,vk.LSHIFT], [vk.TAB]);
        } else {
            //mouse wheel scrolled down
            sp.SendModifiedVKeys([vk.LCONTROL], [vk.TAB]);
        }
    } else {
        sp.MouseWheel(wheel.Point, false, wheel.Delta); 
    }
} else if(mouseLocation.X <= currentScreen.Bounds.Left + 20) {
    if(wheel.Delta > 0){
        //scroll up, send 
        ScreenBrightness.ScreenBrightness.Adjust("10+");
    } else {
        //scroll down, send 
        ScreenBrightness.ScreenBrightness.Adjust("10-");
    }
} else if(mouseLocation.X >= currentScreen.Bounds.Right - 25) {
    if(wheel.Delta > 0) {
        //If Alt is down
        try { 
            if(sp.GetStoredBool("AltDown")) {
                sp.SendModifiedVKeys([vk.LSHIFT], [vk.TAB]);
            } else {
                sp.StoreBool("AltDown", true); 
                sp.SendAltDown();
                sp.Sleep(50);
                sp.SendModifiedVKeys([vk.LSHIFT], [vk.TAB]);
            }

            sp.CreateTimer("TimerAltDown", 800, 0, `sp.SendAltUp(); sp.DeleteTimer("TimerAltDown");`);
            sp.DeleteStoredBool("AltDown");

        } catch {}
    } else {
    //If Alt is down
        try { 
           if(sp.GetStoredBool("AltDown")) {
                sp.SendVKeyDown(vk.TAB);
                sp.Sleep(50);
                sp.SendVKeyUp(vk.TAB);

            } else {
            //First stroll, send Alt down
                sp.StoreBool("AltDown", true); 
                sp.SendAltDown();
                sp.Sleep(50);
                sp.SendVKeyDown(vk.TAB);
                sp.Sleep(50);
                sp.SendVKeyUp(vk.TAB);
            }

            sp.CreateTimer("TimerAltDown", 800, 0, `sp.SendAltUp(); sp.DeleteTimer("TimerAltDown");`);
            sp.DeleteStoredBool("AltDown");
        } catch {}
    }
} else {
    //Default, pass mouse wheel message onto the original control
    sp.MouseWheel(wheel.Point, false, wheel.Delta); 
}


1 Like

最小化到托盘、最小化指定窗口到托盘(指定窗口设置老板键)

下载插件https://www.strokesplus.net/files/plugins/MinToTrayPlugin_1.2.zip

下载后解压,/bin/Release文件夹获取MinToTrayPlugin.dll,插件-添加插件

以Chrome为例,设置老板键 (Hotkey),按下最小化到托盘,再次按下激活窗口并置前

如果需要同时最小化其他窗口,参照wndx继续添加名称(可以是容易识别的部分)

var wndx = sp.WindowsFromTitlePartial("- Google Chrome");

if(wndx.Count === 0) {
} else {
    if(!sp.GetStoredBool("WindowInTray")) {
        MinToTray.SendToTray(wndx.First().HWnd);
        sp.StoreBool('WindowInTray', true);
    } else {
        wndx.First().Activate();
        sp.StoreBool('WindowInTray', false);
    }
}

定时执行动作/启动程序

比如工作日,早上9点自动启动Chrome

添加到全局动作-启动/退出
路径4个反斜杠\

sp.CreateTimer("TimeandScreenWatch",
                               250,
                               250,
                               `var d = new Date();
                               if(d.getDay() !== 5 && d.getDay() !== 6 && ("0" + d.getHours()).slice(-2) == 09 && ("0" + d.getMinutes()).slice(-2) == 00 && ("0" + d.getSeconds()).slice(-2) == 00) {
                                   sp.RunOrActivate('C:\\\\Program Files\\\\Google\\\\Chrome\\\\Application\\\\chrome.exe');
                               }`
);

桌面显示倒计时

输入截止时间后,桌面显示倒计时,结束后发出嘀声

时间格式
年, 月, 日, 时, 分(可选), 秒(可选)
比如 ‘2022,3,8,12,30’ or ‘22,3,8,12,30’ or ‘22,3,8,12,30,30’

年-月-日-时-分(可选)-秒(可选)
比如 ‘2022-3-8-12-30’ or ‘22-3-8-12-30’ or ‘22-3-8-12-30-30’

回车,执行,ESC,退出

第一部分

添加到全局动作-启动/退出

重要:如果已经添加过DisplayTextInfo计时器,直接复制添加if(sp.GetStoredBool("countDownTime")) {}之间的代码(即开始结束之间)

sp.CreateTimer("LangWatch", 
               250, 
               250, 
               `var info = new DisplayTextInfo();
              
               info.TitleFont = new Font('Segoe UI', 12, host.flags(FontStyle.Bold));
               info.MessageFont = new Font("Segoe UI Semibold", 12);
               info.BackColor = "15,179,98"; 
               info.ForeColor = "255,255,255";
               info.Duration = 1000;
               info.Opacity = 0.5;
               info.Location = "190,809"; 
               info.FadeSteps = 5;
               info.Padding = 10;
               info.Message = "";

               //开始
               if(sp.GetStoredBool("countDownTime")) {
                    var getStrTime = sp.GetStoredString('strTime');
                    //sp.ConsoleLog(getStrTime)
                    if(getStrTime.indexOf(',') > -1) {
                        var yearSet = ("20" + (getStrTime.split(',')[0])).slice(-4);
                        var monSet = ("0" + (parseInt(getStrTime.split(',')[1]) - 1)).slice(-2);
                        var daySet = ("0" + (getStrTime.split(',')[2])).slice(-2);
                        var hourSet = getStrTime.split(',')[3] != null ? ("0" + (getStrTime.split(',')[3])).slice(-2) : "00";
                        var minSet = getStrTime.split(',')[4] != null ? ("0" + (getStrTime.split(',')[4])).slice(-2) : "00";
                        var secSet = getStrTime.split(',')[5] != null ? ("0" + (getStrTime.split(',')[5])).slice(-2) : "00";
                    } else if(getStrTime.indexOf('-') > -1) {
                        var yearSet = ("20" + (getStrTime.split('-')[0])).slice(-4);
                        var monSet = ("0" + (parseInt(getStrTime.split('-')[1]) - 1)).slice(-2);
                        var daySet = ("0" + (getStrTime.split('-')[2])).slice(-2);
                        var hourSet = getStrTime.split('-')[3] != null ? ("0" + (getStrTime.split('-')[3])).slice(-2) : "00";
                        var minSet = getStrTime.split('-')[4] != null ? ("0" + (getStrTime.split('-')[4])).slice(-2) : "00";
                        var secSet = getStrTime.split('-')[5] != null ? ("0" + (getStrTime.split('-')[5])).slice(-2) : "00";
                    }
 
                    var newTime = new Date(parseInt(yearSet), parseInt(monSet), parseInt(daySet), parseInt(hourSet), parseInt(minSet), parseInt(secSet));

                    var diff = parseInt((newTime - Date.now()) / 1000);
                    var sec = parseInt(diff % 60);
                    var min = parseInt((diff / 60) % 60);
                    var hour = parseInt(diff / 3600);
                    var day = parseInt(diff / 3600 / 24);
                    var lastime = hour + "Hour" + min + "Min" + sec + "Sec";

                    if(hour == 0 && min == 0 && sec == 0) {
                        sp.StoreBool('countDownTime', false);
                        sp.DeleteStoredString('strTime');
                        System.Console.Beep(800, 1000);
                    }

                    if(info.Message.length > 0) {
                        info.Message += " - ";
                        info.BackColor = "255,105,180";//pink
                        info.Location = "90,809";
                    } else {
                        info.BackColor = "56,142,142";//green
                        info.Location = "225,809";
                    }
                    info.Message += lastime;  
                } 
                //结束

                try {

                } catch {}  


                if(info.Message.length > 0) { 
                    if(sp.GetStoredBool("LangShown")) {
                        sp.DisplayTextUpdate(info);
                    } else { 
                        sp.DisplayText(info);
                        sp.StoreBool("LangShown", true);
                    }
                } else {
                    sp.DisplayTextClose();
                    sp.StoreBool("LangShown", false);
                }
               `
);

第二部分

执行动作

if(!sp.GetStoredBool('countDownTime')) {
    var input = shouInput();
    //sp.ConsoleLog(input);
    if(input != '') {
        sp.StoreString('strTime', input);
        sp.StoreBool('countDownTime', true);
    }
} else {
    sp.StoreBool('countDownTime', false);
    sp.DeleteStoredString('strTime');
}


function shouInput() {
    var ht = sp.ForegroundWindow().Screen.Bounds.Height;
    var wd = sp.ForegroundWindow().Screen.Bounds.Width;

    var input = "";

    var Forms = forms.System.Windows.Forms;
    var form = new Forms.Form;

    form.StartPosition = Forms.FormStartPosition.Manual;
    form.FormBorderStyle = Forms.FormBorderStyle.FixedToolWindow;
    form.TopMost = true;
    form.ControlBox = false;
    form.ShowInTaskbar = false;
    form.Margin = new Forms.Padding(0);
    form.Padding = new Forms.Padding(1); 
    form.MinimumSize = new Size(100, 10);
    //form.Size = new Size(300, 26);
    form.Size = new Size(300, 34);
    //form.Location = currentMouseLocation;
    form.Location = new Point(wd/2 - 150, ht/2 - 60);
    form.AutoSize = true;
    form.GetType().GetProperty("DoubleBuffered",
            host.flags(clr.System.Reflection.BindingFlags.NonPublic,
            clr.System.Reflection.BindingFlags.Instance))
            .SetValue(form, true);
    form.BackColor = Color.WhiteSmoke;

    var textBox = new Forms.TextBox;
    textBox.Size = new Size(150, 20);
    textBox.Location = new Point(50, 5);
    //textBox.Font = new System.Drawing.Font("Microsoft YaHei", 8, FontStyle.Regular);
    textBox.Font = new System.Drawing.Font("Microsoft YaHei", 13, FontStyle.Regular);
    textBox.Text = "";
    textBox.Dock = System.Windows.Forms.DockStyle.Fill;
    form.Controls.Add(textBox);

    dragMoveBlind = ShowImageBindDragMove(form, form);
    dragMoveBlind = ShowImageBindDragMove(form, textBox);

    var form_shown = 
    form.Shown.connect(
    function (sender, args) {
        form.TopMost = true;
        form.Activate();
    });

    var textBox_KeyPress = 
    textBox.KeyPress.connect(
    function (sender, e) {
        // The keypressed method uses the KeyChar property to check 
        // whether the ENTER key is pressed. 
        // then, do action and close the Form
        if (e.KeyChar == 13)
        {
            input = textBox.Text;
            form.Close();
        // The keypressed method uses the KeyChar property to check 
        // whether the ESCAPE key is pressed. 
        // then close the Form
        } else if(e.KeyChar == 27) {
            form.Close();
        }
    });

    var textBox_KeyDown = 
    textBox.KeyDown.connect(
    function (sender, e) {
        // The keydown method uses the KeyChar property to check 
        // whether the Ctrl+SHIFT+J key is pressed. 
        // then, close the Form
        var hk = e.KeyCode
        if((e.Control) && (e.KeyCode==System.Windows.Forms.Keys.U) && (e.Shift)) {
            input = '';
            form.Close();
            
        }
    });

    // Enable to double click the mouse right button to 
    // drag the From
    var textBox_doubleClick = 
    textBox.DoubleClick.connect(
    function (sender, args) {
        dragMoveBlind = ShowImageBindDragMove(form, textBox);
    });

    var form_doubleClick = 
    form.DoubleClick.connect(
    function (sender, args) {
        dragMoveBlind = ShowImageBindDragMove(form, form);
    });

    Forms.Application.Run(form);

    var regmin = /^([1-9]\d{3}|2[0-9]),([1-9]|1[0-2]),([1-9]|[1-2][0-9]|3[0-1]),([0-9]|[1-2][0-3]),([0-9]|[0-5][0-9])$/;
    var reghour = /^([1-9]\d{3}|2[0-9]),([1-9]|1[0-2]),([1-9]|[1-2][0-9]|3[0-1]),([0-9]|[1-2][0-3])$/;
    var _regmin = /^([1-9]\d{3}|2[0-9])-([1-9]|1[0-2])-([1-9]|[1-2][0-9]|3[0-1])-([0-9]|[1-2][0-3])-([0-9]|[0-5][0-9])$/;
    var _reghour = /^([1-9]\d{3}|2[0-9])-([1-9]|1[0-2])-([1-9]|[1-2][0-9]|3[0-1])-([0-9]|[1-2][0-3])$/;
    if(input == '') {
        return input;
    } else {
        if(input.match(regmin) || input.match(reghour) ||input.match(_regmin) || input.match(_reghour)) {
            return input;
        } else {
            return shouInput();
        }
    }

    function ShowImageBindDragMove(form, item) {
        var Cursors = forms.System.Windows.Forms.Cursors;
        var ReleaseCapture = sp_config.GetType().Assembly.GetType("API").GetMethod("ReleaseCapture");

        var item_mouseMove = 
        item.MouseMove.connect(
        function (sender, e) {
            var hitResize = form.Height + form.Width - (e.X + e.Y) < 30;
            var cursor = hitResize ? Cursors.SizeNWSE : Cursors.IBeam;
            if (item.Cursor != cursor) item.Cursor = cursor;
            if (e.Button == MouseButtons.Left) {
                ReleaseCapture.Invoke(null, null);
                sp.WindowFromHandle(form.Handle).SendMessageObj(0x0112,
                    hitResize ? 0xF008 : 0xF012, 0);
            }
        });

        return [item_mouseMove];
    }
}

发现有个问题,这个和上面的截图,双击关闭后没有清除内存,S+截图多了占用内存会越来越多。下面的截图没试用

测试了一天,不知道是不是真的清理了内存,S+内存占用会过一会降低,使用以下代码,再更新3#的代码,帮忙测试下

添加到启动/退出里面

if(!NativeModules.Kernel32)
{    

    var kernel32TB = sp.NativeModule().DefineType("Kernel32", "Class,Public,SequentialLayout,Serializable");

    var IntPtrT = host.typeOf(clr.System.IntPtr);
    var Int32T = host.typeOf(clr.System.Int32);
    var BooleanT = host.typeOf(clr.System.Boolean);
    kernel32TB.DefinePInvokeMethod("SetProcessWorkingSetSize",
								 "kernel32.dll",
								 [IntPtrT,Int32T,Int32T], 
								 BooleanT, 
								 "PreserveSig");
	kernel32TB.Create();
}


添加了之后,应用直接报错了

S+版本号是多少呢,测试0.5.5.7、0.5.6.5添加正常

找了好久的手势脚本 非常感谢 特地注册账号收藏评论