Jump to content
Sign in to follow this  
YellowAfterlife

user32.dll/VkKeyScan - not doing it right?

Recommended Posts

YellowAfterlife

Hello there.

I'm trying to get function VkKeyScan from user32.dll to work, to avoid making an awkward switch or hashtable to convert keys for other DLL calls.

According to MSDN, function is defined as

short VkKeyScan(TCHAR ch)

My current code is:

func _VkKeyScan($ch)
    local $aResult = dllCall('user32.dll', 'short', 'VkKeyScan', 'int', $ch)
    if (@error) then
        consoleWrite('(debug) Something did not work.')
        return setError(@error, @extended, '')
    endif
    return $aResult
endfunc

With the following used to test it:

local $sym = 'A'
consoleWrite('vkKeyScan for [' & $sym & '] = [' & string(_vkKeyScan($sym)) & ']' & @CR)

However, no matter what is in, nothing is out. Not an error, not anything else.

vkKeyScan for [A] = []

I have also tried 'int' for return type, and 'str' for input type, but no results.

What am I doing wrong here?

Share this post


Link to post
Share on other sites
ProgAndy

It would be even better to use Unicode (VkKeyScanW, AscW)

ConsoleWrite('vkKeyScan for [' & "a" & '] = [' & _vkKeyScan("a") & ']' & @CR)

; return value is VK code
; @extended contains shift state
Func _VkKeyScan($s_Char)
     Local $a_Ret = DllCall("user32.dll", "short", "VkKeyScanW", "ushort", AscW($s_Char))
     If @error Then Return SetError(@error, @extended, -1)
     Return SetExtended(BitShift($a_Ret[0], 8), BitAnd($a_Ret[0], 0xFF))
EndFunc
Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites
YellowAfterlife

It would be even better to use Unicode (VkKeyScanW, AscW)

ConsoleWrite('vkKeyScan for [' & "a" & '] = [' & _vkKeyScan("a") & ']' & @CR)

; return value is VK code
; @extended contains shift state
Func _VkKeyScan($s_Char)
     Local $a_Ret = DllCall("user32.dll", "short", "VkKeyScanW", "ushort", AscW($s_Char))
     If @error Then Return SetError(@error, @extended, -1)
     Return SetExtended(BitShift($a_Ret[0], 8), BitAnd($a_Ret[0], 0xFF))
EndFunc

And if one needs combined value (same as when using from WINAPI), function would look like this?

Func _VkKeyScan($s_Char)
    Local $a_Ret = DllCall("user32.dll", "short", "VkKeyScan", "ushort", AscW($s_Char))
    If @error Then Return SetError(@error, @extended, -1)
Return $a_Ret[0]
EndFunc

My intent here is to pass key to PostMessage, so chosen application would receive keyboard event:

local $h = winGetHandle('[CLASS:Notepad]')
local $k = _VkKeyScan('A')
$WM_KEYDOWN = 0x0100
$WM_KEYUP = 0x0101
consoleWrite('handle: ' & string($h) & @CR)
consoleWrite('vkey: ' & string($k) & @CR)
DllCall('user32.dll', 'int', "PostMessage", 'hwnd', $h, 'uint', $WM_KEYDOWN, 'uint', $k, 'uint', 0x00140001)
sleep(50)
DllCall('user32.dll', 'int', "PostMessage", 'hwnd', $h, 'uint', $WM_KEYUP, 'uint', $k, 'uint', 0xC0014001)
However this does not work - application does not react (in both cases of notepad and target one), and no errors are raised.

"Magic numbers" in code are repeat=1,oem=20,transitionState=0/1

Reason for trying to do this rather than sendsendKeepActive is that amount of keys to be typed in may vary, and it is preferred that other programs could be used on machine while keyboard events are sent.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×