Author |
Topic |
|
Dimka
Russia
5 Posts |
Posted - 11/22/2012 : 22:27:30
|
First of all, many, many thanks for S+.
Is there a way, trick, to display via acDisplayText() the keyboard input language, which is becoming active? (I use SendAlt & SendShift combination to switch between them, and it would be very good to bring info to the screen for some little time).
|
|
Rob
USA
2615 Posts |
Posted - 11/23/2012 : 00:59:51
|
Since I don't have an international setup, it's difficult for me to field these types of requests.
However, I have been able to display the language ID for my system (409) by putting this into the Global Lua tab:
aliencore = alien.core
user32 = aliencore.load("user32.dll")
-- ************ GetKeyboardLayoutName ************
gGetKeyboardLayoutName = user32.GetKeyboardLayoutNameA
gGetKeyboardLayoutName:types{ ret = 'long', abi = 'stdcall', 'pointer'}
function aGetKeyboardLayoutName()
sLayout = ""
gGetKeyboardLayoutName(sLayout)
return sLayout
end
And this into an action:
acDisplayText(aGetKeyboardLayoutName(), "Arial", 42, 1500, 0, 0, 455, 100, 100)
The sLayout receives the layout byref and seems to be lost if you do anything to the string, and it doesn't like matching in a comparison...I'll dig a little deeper when I have some time as (oddly enough) I'm not a Lua expert at all
Hopefully this does something for you. |
|
|
Dimka
Russia
5 Posts |
Posted - 11/23/2012 : 01:29:26
|
Yes, that's completely enough for me. Thank you, Rob.
Update. With your's script example I always get 409, no correlation with actual input language. Maybe some another Get... from user32.dll? |
Edited by - Dimka on 11/23/2012 02:29:36 |
|
|
Rob
USA
2615 Posts |
Posted - 11/23/2012 : 08:06:31
|
Honestly, it was a complete stab in the dark in hoping it would show something different for another language
I'll have to look around some more. |
|
|
Rob
USA
2615 Posts |
Posted - 11/23/2012 : 08:08:42
|
Judging by the name, perhaps it's only the keyboard's layout, nothing to do with the language selected. Meaning, the physical keyboard hasn't changed in any way, which may be what that function is retrieving. Again, pure speculation at this point. |
|
|
Rob
USA
2615 Posts |
Posted - 11/23/2012 : 08:36:39
|
Actually, I think it's because input language is per thread. So Notepad can have one language, Word another, etc. The call is returning the language of the action thread in S+, which would likely be 409.
This may be a tricky thing to accomplish since applications can have many threads, which makes it very difficult to put this into an action as you don't know what thread to specify. For example, getting the foreground window we can determine the process ID easily (since there's only one per instance of a program); but internally, the app can potentially have dozens of threads, and I can't (thus far) find a way to programmatically determine the thread which is handling the input for a program.
The only way it seems would be to register a system-wide Windows message hook and capture the WM_INPUTLANGCHANGE message (which the program with focus receives when the input language is changed). However, that's something we can't do in a Lua script and isn't something I want to add to S+ as it just adds constant overhead for only a single use.
|
|
|
Dimka
Russia
5 Posts |
Posted - 11/23/2012 : 21:07:36
|
Understood, Rob. |
Edited by - Dimka on 11/23/2012 21:10:13 |
|
|
Rob
USA
2615 Posts |
Posted - 11/24/2012 : 11:37:04
|
Ah ha! Thanks to some folks over at stackoverflow.com, I think I've got something. Now, it's not guaranteed to work as there may be some circumstances where the thread that created the window is not the one that is processing input, but there's a pretty good chance it will work most of the time. I've tested it in a few apps (installed the Simplified Chinese keyboard layout, and using the Alt+Shift to switch) and it's working fine.
Ok, so in the Global Lua tab:
aliencore = alien.core
user32 = aliencore.load("user32.dll")
-- ************ GetKeyboardLayout ************
gGetKeyboardLayout = user32.GetKeyboardLayout
gGetKeyboardLayout:types{ ret = 'long', abi = 'stdcall', 'long'}
function aGetKeyboardLayout(threadID)
return gGetKeyboardLayout(threadID)
end
-- ************ GetWindowThreadProcessId ************
gGetWindowThreadProcessId = user32.GetWindowThreadProcessId
gGetWindowThreadProcessId:types{ ret = 'long', abi = 'stdcall', 'long', 'pointer'}
function aGetWindowThreadProcessId(hwnd)
local threadID = 0
threadID = gGetWindowThreadProcessId(hwnd, threadID)
return threadID
end
The action:
local iLangID = bit32.rshift(aGetKeyboardLayout(aGetWindowThreadProcessId(acGetOwnerWindowByPoint(gsx,gsy))),16)
if iLangID == 1033 then
sLang = "English - United States"
elseif iLangID == 2052 then
sLang = "Chinese - People's Republic of China"
end
acDisplayText(sLang, "Arial", 42, 255, 0, 0, 1200, 100, 100)
See this link for the list of locale IDs (the 1033 and 2052 above) for the language(s) you need: http://msdn.microsoft.com/en-us/goglobal/bb964664.aspx
Note that this is setup to get the language of the window that's under the mouse cursor where the gesture began. I can help you change that if you need to, but test it out as-is to see if it works for you. |
|
|
Dimka
Russia
5 Posts |
Posted - 11/24/2012 : 14:58:06
|
Wonderful, it works now. Thanks. One thing I have to mention: execution of acDisplayText() makes whole screen to flick once. Is there a way to prevent flickering (OS is XP)? |
|
|
Rob
USA
2615 Posts |
Posted - 11/24/2012 : 15:32:05
|
Unfortunately not on XP. The overlay window which displays the text message is a full screen transparent window which is created when you call acDisplayText and is destroyed when the duration has passed. On XP, this causes a flicker when Windows blends and refreshes certain UI elements below the (mostly) transparent window.
The gesture draw window can be set to stay on top to prevent the flicker when drawing gestures, but the display text window doesn't stay running and thus there's no way around it. Clearly there could be a better way to handle this, and I've tried many times (without rewriting major sections of the code), but that's just the way it is for the time being.
At some point, I will likely end up rewriting S+ from the ground up, now that I have much more experience and a better idea of many use cases/issues/requests I hadn't thought of when I started writing S+. |
|
|
Dimka
Russia
5 Posts |
Posted - 11/24/2012 : 15:57:33
|
I see. Also text comes out white outlined. Maybe you can modify acDisplayText() with one more input param and make it able to draw colored background under chars? |
|
|
Rob
USA
2615 Posts |
Posted - 11/24/2012 : 19:50:10
|
Well, since specifying a BG color of the text will draw a full rectangle of the color behind the text, I've decided to set the color key of the window to match the BG of the text, which will both be only a single tick off from the specified text color. This eliminates the white outline but doesn't affect anything else.
I'll release that in 2.4.3. |
|
|
babakm
58 Posts |
|
perpleks
2 Posts |
Posted - 03/28/2018 : 10:12:15
|
Unfortunately, StrokesPlus crashes under Windows 10 with this code :( Is it possible to resolve this issue somehow? |
|
|
perpleks
2 Posts |
Posted - 03/28/2018 : 11:03:38
|
It seems like problem is in GetWindowThreadProcessId function, so I've simply omitted it, since in Windows 10 language change is system-wide by default.
My objective was to use strokes plus with Firefox instead of mouse gestures addon (they do not work with some tabs since webextensions disaster, e.g. new empty tab) and I was having problems with "Close tab" gesture due to S+ lack of proper multilanguage support. In the end I've came up with this gesture code:
local iLangID = bit32.rshift(aGetKeyboardLayout(0),16)
if iLangID == 1049 then
acSendKeys("^ö")
elseif iLangID == 1033 then
acSendKeys("^w")
end
Works nicely |
Edited by - perpleks on 03/28/2018 11:05:08 |
|
|
|
Topic |
|
|
|