StrokesPlus.net
Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Options
Go to last post Go to first unread
Rob Otter  
#1 Posted : Tuesday, November 24, 2020 10:51:20 PM(UTC)
Rob Otter

Rank: Advanced Member

Reputation:

Groups: Approved
Joined: 10/26/2020(UTC)
Posts: 50
Germany
Location: Darmstadt

Thanks: 15 times
Was thanked: 2 time(s) in 2 post(s)
I wanted to use Ctrl key multiple presses as a hotkey and came up with this Global Actions --> Load script.
After the first Ctrl press, it counts the subsequent Ctrl presses within one second and acts according to their number.

Not that I want to impress anyone with my genius coding skills but like to know if this is a good way of doing so - or is there a more elegant way?

Edit: Updated code following Rob´s comments.
Edit2: I added " && !keyboardHookEvent.Injected" to the check because otherwise a multi-keypress is discovered even if S+ is sending keystrokes because of other actions initiated by the user (I have several gestures for copy, paste, cut, undo, ... and they all involve the Ctrl key):

Code:
// This subscribes for an asynchronous keyboard hook event
// Dont forget to enable Keyboard Hook Event Subscription in Options! 
var keyboardEventObj = sp.GetStoredObject("keyboardEvent");
var keyPressTimeout = 1000; // 1 second
sp.StoreNumber("ctrlKeyPressCounter", 0);

if (!keyboardEventObj.GetType().FullName.includes('EventConnection')) {
    var keyboardEvent = KeyboardHook.OnKeyboardHookEventAsync.connect(
        function (sender, keyboardHookEvent) {
            try {
                if (keyboardHookEvent.Key == vk.LCONTROL && keyboardHookEvent.KeyState == KeyState.Up && !keyboardHookEvent.Injected) {
                    sp.StoreNumber("ctrlKeyPressCounter", sp.GetStoredNumber("ctrlKeyPressCounter") + 1);
                    if (sp.GetStoredNumber("ctrlKeyPressCounter") == 1) {
                        // Start Timer
                        sp.CreateTimer('CtrlKeyTimeout', keyPressTimeout, -1,  String.raw`
                            // React on number of key presses:
                            switch (sp.GetStoredNumber("ctrlKeyPressCounter")) {
                                case 1:
                                    // Don´t do anything to keep original function and not interfere with several
                                    // hotkey combinations (ctrl-c, ctrl-s, ...)
                                    break;
                                case 2:
                                    eval(sp.GetMacroScript("Functions", "MouseRestrict1D"));
                                    break;
                                case 3:
                                    // Do other amazing stuff
                                    break;
                                default:
                                    sp.MessageBox("# pressed Ctrl: " + sp.GetStoredNumber("ctrlKeyPressCounter"), "Message from S+");
                                break;
                            }
                            sp.StoreNumber("ctrlKeyPressCounter", 0);
                            sp.DeleteTimer('CtrlKeyTimeout');
                        `);
                    }
                }
            }
            catch(err) {
                sp.MessageBox("An error occured while processing CTRL hotkey:\n\n" + err.message, "Message from S+");
            }
        }
    );
    sp.StoreObject("keyboardEvent", keyboardEvent);
}

Edited by user Tuesday, December 22, 2020 11:13:38 AM(UTC)  | Reason: Not specified

Rob  
#2 Posted : Tuesday, November 24, 2020 11:03:49 PM(UTC)
Rob

Rank: Administration

Reputation:

Groups: Translators, Members, Administrators
Joined: 1/11/2018(UTC)
Posts: 1,349
United States
Location: Tampa, FL

Thanks: 28 times
Was thanked: 416 time(s) in 354 post(s)
Looks good to me. The only thing I would change is using sp.StoreNumber and sp.GetStoredNumber to hold the counter value.

On my phone, so can't give you a nice example...but while ctrlKeyPressCounter is defined in Load and will exist in all script engines, it will only be incremented in the script engine handling the keyboard hook event.

The timer will execute in the context of an undetermined script engine, where ctrlKeyPressCounter may still be zero.

Using store/get number, the value is stored internally and each engine sees the same value.
Rob  
#3 Posted : Tuesday, November 24, 2020 11:12:29 PM(UTC)
Rob

Rank: Administration

Reputation:

Groups: Translators, Members, Administrators
Joined: 1/11/2018(UTC)
Posts: 1,349
United States
Location: Tampa, FL

Thanks: 28 times
Was thanked: 416 time(s) in 354 post(s)
Each script engine is isolated from each other. Load executes the same script in each one, but the values are not linked; they each have their own ctrlKeyPressCounter with its own value.
Rob  
#4 Posted : Tuesday, November 24, 2020 11:29:17 PM(UTC)
Rob

Rank: Administration

Reputation:

Groups: Translators, Members, Administrators
Joined: 1/11/2018(UTC)
Posts: 1,349
United States
Location: Tampa, FL

Thanks: 28 times
Was thanked: 416 time(s) in 354 post(s)
sp.StoreNumber("ctrlKeyPressCounter", sp.GetStoredNumber("ctrlKeyPressCounter")++);

And

switch (sp.GetStoredNumber("ctrlKeyPressCounter"))

For example.
thanks 1 user thanked Rob for this useful post.
Rob Otter on 11/25/2020(UTC)
Rob Otter  
#5 Posted : Wednesday, November 25, 2020 6:57:57 AM(UTC)
Rob Otter

Rank: Advanced Member

Reputation:

Groups: Approved
Joined: 10/26/2020(UTC)
Posts: 50
Germany
Location: Darmstadt

Thanks: 15 times
Was thanked: 2 time(s) in 2 post(s)
Thanks for your feedback and especially the explanation - I´ve learned something new today. Would it be better to specify a distinct engine? I think I have not understood the concept of engines yet.

Just as a feedback for you, sp.GetStoredNumber("ctrlKeyPressCounter")++ does not work, the error message says: "Invalid left-hand side expression in postfix operation".
Replacing it with sp.GetStoredNumber("ctrlKeyPressCounter")+1 works fine.

Anyway, I will update my above code following your advices.
Rob  
#6 Posted : Wednesday, November 25, 2020 8:00:10 AM(UTC)
Rob

Rank: Administration

Reputation:

Groups: Translators, Members, Administrators
Joined: 1/11/2018(UTC)
Posts: 1,349
United States
Location: Tampa, FL

Thanks: 28 times
Was thanked: 416 time(s) in 354 post(s)
Quote:
Would it be better to specify a distinct engine?


That wouldn't matter as the timer threads just pick the first engine available (not currently executing).

Edited by user Wednesday, November 25, 2020 8:05:08 AM(UTC)  | Reason: Not specified

petercncn  
#7 Posted : Tuesday, December 1, 2020 3:54:18 PM(UTC)
petercncn

Rank: Member

Reputation:

Groups: Approved
Joined: 11/4/2020(UTC)
Posts: 12
China

Thank you for your code, I modified and update to this:
//===== 多次按左Ctrl执行不同命令,开始
// 参考:https://forum.strokesplus.net/posts/t8266findunread-Double-CTRL-press-as-hotkey---a-good-approach,
//参考: https://forum.strokesplu...oard-Event-Subscriptions
// This subscribes for an asynchronous keyboard hook event
// Dont forget to enable Keyboard Hook Event Subscription in Options!
var keyboardHookEventLctrl = sp.GetStoredObject("keyboardEvent");
var keyPressTimeoutLctrl = 1000; // 1 second
sp.StoreNumber("LctrlKeyPressCounter", 0);

if (!keyboardHookEventLctrl.GetType().FullName.includes('EventConnection')) {
var keyboardEventLctrl = KeyboardHook.OnKeyboardHookEventAsync.connect(
function (sender, keyboardHookEvent) {
try {
if (keyboardHookEvent.Key == vk.LCONTROL && keyboardHookEvent.KeyState == KeyState.Up) {
sp.StoreNumber("LctrlKeyPressCounter", sp.GetStoredNumber("LctrlKeyPressCounter") + 1);
if (sp.GetStoredNumber("LctrlKeyPressCounter") == 1) {
// Start Timer
sp.CreateTimer('LctrlKeyTimeout', keyPressTimeoutLctrl, -1, String.raw`
// React on number of key presses:
switch (sp.GetStoredNumber("LctrlKeyPressCounter")) {
case 1:
// Don´t do anything to keep original function and not interfere with several
// hotkey combinations (ctrl-c, ctrl-s, ...)
break;
case 2:
// Don´t do anything to keep original function and not interfere with several
break;
case 3:
// Do some amazing stuff, 连续按3次左ctrl,执行以下自定义的命令。由于两次ctrl是Listary的热
//键,Listary会获得焦点,所以多次左ctrl执行的命令应为不需要特定焦点的全局命令或宏。
// eval(sp.GetMacroScript("Functions", "MouseRestrict1D"));
sp.SendModifiedVKeys([vk.LWIN], [vk.VK_E]); //连续按3次左ctrl 为打开我的电脑

break;

case 4:
// Do some amazing stuff,暂时空置
sp.SendVKey(vk.VOLUME_MUTE); //连续按4次左ctrl 为切换静音

break;

default:
// sp.MessageBox("# pressed LCtrl: " + sp.GetStoredNumber("LctrlKeyPressCounter"), "Message from S+");
var currpt = sp.GetCurrentMousePoint();var info = new DisplayTextInfo();
info.Title = "一共" + sp.GetStoredNumber("LctrlKeyPressCounter") + "次";
info.Message = "已连续按左Ctrl键" ;
info.Location = (currpt.X-100)+','+(currpt.Y-150);
info.Duration = 2000;info.TitleAlignment = "Center";info.Opacity = 0.7;info.MessageAlignment = "Left";info.TitleFont = new Font("Segoe UI", 33, host.flags(FontStyle.Bold));info.MessageFont = new Font("Segoe UI Semibold", 17);info.BackColor = "black";info.ForeColor = "white";info.Padding = 5;
sp.DisplayText(info);

break;
}
sp.StoreNumber("LctrlKeyPressCounter", 0);
sp.DeleteTimer('LctrlKeyTimeout');
`);
}
}
}
catch(err) {
sp.MessageBox("An error occured while processing LCTRL hotkey:\n\n" + err.message, "Message from S+");

}
}
);
sp.StoreObject("keyboardEvent", keyboardEventLctrl);
}
//=====多次按左Ctrl执行不同命令,结束

//===== 多次按右Ctrl执行不同命令,开始
// 参考:https://forum.strokesplus.net/posts/t8266findunread-Double-CTRL-press-as-hotkey---a-good-approach,
//参考: https://forum.strokesplu...oard-Event-Subscriptions

// This subscribes for an asynchronous keyboard hook event
// Dont forget to enable Keyboard Hook Event Subscription in Options!
var keyboardHookEventRctrl = sp.GetStoredObject("keyboardEventRctrl");
var keyPressTimeoutRctrl = 1000; // 1 second
sp.StoreNumber("RctrlKeyPressCounter", 0);

if (!keyboardHookEventRctrl.GetType().FullName.includes('EventConnection')) {
var keyboardEventRctrl = KeyboardHook.OnKeyboardHookEventAsync.connect(
function (sender, keyboardHookEventRctrl) {
try {
if (keyboardHookEventRctrl.Key == vk.RCONTROL && keyboardHookEventRctrl.KeyState == KeyState.Up) {
sp.StoreNumber("RctrlKeyPressCounter", sp.GetStoredNumber("RctrlKeyPressCounter") + 1);
if (sp.GetStoredNumber("RctrlKeyPressCounter") == 1) {
// Start Timer
sp.CreateTimer('RctrlKeyTimeout', keyPressTimeoutRctrl, -1, String.raw`
// React on number of key presses:
switch (sp.GetStoredNumber("RctrlKeyPressCounter")) {
case 1:
// Don´t do anything to keep original function and not interfere with several
// hotkey combinations (ctrl-c, ctrl-s, ...)
break;
case 2:
// Don´t do anything to keep original function and not interfere with several
break;
case 3:
// Do some amazing stuff, 连续按3次右ctrl,执行以下自定义的命令。由于两次ctrl是Listary的热
//键,Listary会获得焦点,所以多次右ctrl执行的命令应为不需要特定焦点的全局命令或宏。
// eval(sp.GetMacroScript("Functions", "MouseRestrict1D"));
sp.SendModifiedVKeys([vk.LWIN], [vk.VK_E]); //连续按3次右ctrl 为打开我的电脑

break;

case 4:
// Do some amazing stuff,暂时空置
sp.SendVKey(vk.VOLUME_MUTE); //连续按4次右ctrl 为切换静音

break;

default:
// sp.MessageBox("# pressed RCtrl: " + sp.GetStoredNumber("RctrlKeyPressCounter"), "Message from S+");
var currpt = sp.GetCurrentMousePoint();var info = new DisplayTextInfo();
info.Title = "一共" + sp.GetStoredNumber("RctrlKeyPressCounter") + "次";
info.Message = "已连续按右Ctrl键" ;
info.Location = (currpt.X-100)+','+(currpt.Y-150);
info.Duration = 2000;info.TitleAlignment = "Center";info.Opacity = 0.7;info.MessageAlignment = "Left";info.TitleFont = new Font("Segoe UI", 33, host.flags(FontStyle.Bold));info.MessageFont = new Font("Segoe UI Semibold", 17);info.BackColor = "black";info.ForeColor = "white";info.Padding = 5;
sp.DisplayText(info);
break;
}
sp.StoreNumber("RctrlKeyPressCounter", 0);
sp.DeleteTimer('RctrlKeyTimeout');
`);
}
}
}
catch(err) {
sp.MessageBox("An error occured while processing RCTRL hotkey:\n\n" + err.message, "Message from S+");

}
}
);
sp.StoreObject("keyboardEventRctrl", keyboardEventRctrl);
}
//=====多次按右Ctrl执行不同命令,结束

//===== 多次按左Alt执行不同命令,开始
// 参考:https://forum.strokesplus.net/posts/t8266findunread-Double-CTRL-press-as-hotkey---a-good-approach,
//参考: https://forum.strokesplu...oard-Event-Subscriptions

// This subscribes for an asynchronous keyboard hook event
// Dont forget to enable Keyboard Hook Event Subscription in Options!
var keyboardHookEventLALT = sp.GetStoredObject("keyboardEventLALT");
var keyPressTimeoutLALT = 1000; // 1 second
sp.StoreNumber("LALTKeyPressCounter", 0);

if (!keyboardHookEventLALT.GetType().FullName.includes('EventConnection')) {
var keyboardEventLALT = KeyboardHook.OnKeyboardHookEventAsync.connect(
function (sender, keyboardHookEventLALT) {
try {
if (keyboardHookEventLALT.Key == vk.LMENU && keyboardHookEventLALT.KeyState == KeyState.Up) {
sp.StoreNumber("LALTKeyPressCounter", sp.GetStoredNumber("LALTKeyPressCounter") + 1);
if (sp.GetStoredNumber("LALTKeyPressCounter") == 1) {
// Start Timer
sp.CreateTimer('LALTKeyTimeout', keyPressTimeoutLALT, -1, String.raw`
// React on number of key presses:
switch (sp.GetStoredNumber("LALTKeyPressCounter")) {
case 1:
// Don´t do anything to keep original function and not interfere with several
// hotkey combinations (ctrl-c, ctrl-s, ...)
break;
case 2:
sp.SendVKey(vk.VOLUME_MUTE); //连续按2次左Alt 为切换静音
break;

case 3:
sp.SendModifiedVKeys([vk.LWIN], [vk.VK_E]); //连续按3次左Alt 为打开我的电脑
break;

case 4:
// Do some amazing stuff,暂时空置
break;

default:
// sp.MessageBox("# pressed LALT: " + sp.GetStoredNumber("LALTKeyPressCounter"), "Message from S+");
var currpt = sp.GetCurrentMousePoint();var info = new DisplayTextInfo();
info.Title = "一共" + sp.GetStoredNumber("LALTKeyPressCounter") + "次";
info.Message = "已连续按左Alt键" ;
info.Location = (currpt.X-100)+','+(currpt.Y-150);
info.Duration = 2000;info.TitleAlignment = "Center";info.Opacity = 0.7;info.MessageAlignment = "Left";info.TitleFont = new Font("Segoe UI", 33, host.flags(FontStyle.Bold));info.MessageFont = new Font("Segoe UI Semibold", 17);info.BackColor = "black";info.ForeColor = "white";info.Padding = 5;
sp.DisplayText(info);
break;
}
sp.StoreNumber("LALTKeyPressCounter", 0);
sp.DeleteTimer('LALTKeyTimeout');
`);
}
}
}
catch(err) {
sp.MessageBox("An error occured while processing LALT hotkey:\n\n" + err.message, "Message from S+");

}
}
);
sp.StoreObject("keyboardEventLALT", keyboardEventLALT);
}
//=====多次按左Alt执行不同命令,结束

//===== 多次按右Alt执行不同命令,开始
// 参考:https://forum.strokesplus.net/posts/t8266findunread-Double-CTRL-press-as-hotkey---a-good-approach,
//参考: https://forum.strokesplu...oard-Event-Subscriptions

// This subscribes for an asynchronous keyboard hook event
// Dont forget to enable Keyboard Hook Event Subscription in Options!
var keyboardHookEventRAlt = sp.GetStoredObject("keyboardEventRAlt");
var keyPressTimeoutRAlt = 1000; // 1 second
sp.StoreNumber("RAltKeyPressCounter", 0);

if (!keyboardHookEventRAlt.GetType().FullName.includes('EventConnection')) {
var keyboardEventRAlt = KeyboardHook.OnKeyboardHookEventAsync.connect(
function (sender, keyboardHookEventRAlt) {
try {
if (keyboardHookEventRAlt.Key == vk.RMENU && keyboardHookEventRAlt.KeyState == KeyState.Up) {
sp.StoreNumber("RAltKeyPressCounter", sp.GetStoredNumber("RAltKeyPressCounter") + 1);
if (sp.GetStoredNumber("RAltKeyPressCounter") == 1) {
// Start Timer
sp.CreateTimer('RAltKeyTimeout', keyPressTimeoutRAlt, -1, String.raw`
// React on number of key presses:
switch (sp.GetStoredNumber("RAltKeyPressCounter")) {
case 1:
// Don´t do anything to keep original function and not interfere with several
// hotkey combinations (ctrl-c, ctrl-s, ...)
break;
case 2:
sp.SendVKey(vk.VOLUME_MUTE); //连续按2次右Alt 为切换静音
break;

case 3:
sp.SendModifiedVKeys([vk.LWIN], [vk.VK_E]); //连续按3次右Alt 为打开我的电脑
break;

case 4:
// Do some amazing stuff,暂时空置
break;

default:
// sp.MessageBox("# pressed RALT: " + sp.GetStoredNumber("RAltKeyPressCounter"), "Message from S+");
var currpt = sp.GetCurrentMousePoint();var info = new DisplayTextInfo();
info.Title = "一共" + sp.GetStoredNumber("RAltKeyPressCounter") + "次";
info.Message = "已连续按右Alt键" ;
info.Location = (currpt.X-100)+','+(currpt.Y-150);
info.Duration = 2000;info.TitleAlignment = "Center";info.Opacity = 0.7;info.MessageAlignment = "Left";info.TitleFont = new Font("Segoe UI", 33, host.flags(FontStyle.Bold));info.MessageFont = new Font("Segoe UI Semibold", 17);info.BackColor = "black";info.ForeColor = "white";info.Padding = 5;
sp.DisplayText(info);
break;
}
sp.StoreNumber("RAltKeyPressCounter", 0);
sp.DeleteTimer('RAltKeyTimeout');
`);
}
}
}
catch(err) {
sp.MessageBox("An error occured while processing RALT hotkey:\n\n" + err.message, "Message from S+");

}
}
);
sp.StoreObject("keyboardEventRAlt", keyboardEventRAlt);
}
//=====多次按右Alt执行不同命令,结束


//=====可以开发可多次按下执行不同命令的按键有:Tab键上方的`键,F1~F12,只需要用上面的代码模板搜索替换RAlt与vk.RMENU即可。
// You can give Alt, `,F1~F12 difinations by using the above sample code with search and repleace "RAlt" and vk.RMENU
Users browsing this topic
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.