The sample is unchanged since I downloaded it about 2 months ago(no binary
differences).
Sorry! I should've been more clear. I was seeking input *before* uploading for
all. <g>
Here's the updated code: http://vb.mvps.org/samples/raw/MSendInput.bas.txt
(Note to Archive: Not sure that'll stay there, after this thread dies down.)
Key points I'm wondering about are,
1) Is a simple 0-255 check sufficient recognition for "Unicode" characters, where
the input variable 'this' is a single character from a longer string?
Private Sub ProcessChar(this As String)
Dim code As Integer
Dim vk As Integer
Dim capped As Boolean
' Determine whether we need to treat as Unicode.
code = AscW(this)
If code >= 0 And code < 256 Then 'ascii
' Add input events for single character, taking capitalization
' into account. HiByte will contain the shift state, and LoByte
' will contain the key code.
vk = VkKeyScan(Asc(this))
capped = CBool(ByteHi(vk) And 1)
vk = ByteLo(vk)
Call StuffBuffer(vk, capped)
Else 'unicode
Call StuffBufferW(code)
End If
End Sub
2) If it's Unicode, that means we skip all the Shiftkey processing, and instead just
do this, right?
Private Sub StuffBufferW(ByVal CharCode As Integer)
' Unicode is relatively simple, in this context?!
' Press and release this key.
With m_Events(m_EvtPtr)
.wVK = 0
.wScan = CharCode
.dwFlags = KEYEVENTF_UNICODE
End With
m_EvtPtr = m_EvtPtr + 1
With m_Events(m_EvtPtr)
.wVK = 0
.wScan = CharCode
.dwFlags = KEYEVENTF_UNICODE Or KEYEVENTF_KEYUP
End With
m_EvtPtr = m_EvtPtr + 1
End Sub
3) What else I've overlooked? <g>
Thanks... Karl
I am by no means an expert in this area, but here is what I know. Char codes
from 128 to 255 have special meaning, depending on whether you are using
ANSI or Unicode. In Unicode, their meaning is fixed regardless of Code Page.
They refer to Latin-1 Supplement, so for instance char code 169 is always
the copyright symbol.
In ANSI, char codes from 128 to 255 have no meaning without the associated
Code Page. So when someone says char code 169 is the copyright symbol, he or
she is wrong. They must also say what Code Page they are talking about.
So you have to add a Unicode flag to treat char codes 128 to 255 properly.
See these articles:
http://en.wikipedia.org/wiki/Basic_Multilingual_Plane
http://en.wikipedia.org/wiki/Unicode
> 2) If it's Unicode, that means we skip all the Shiftkey processing, and
> instead just do this, right?
It seems so. It seems that in order to get keyboard scan codes, keyboard
layout and support for specific code pages has to be loaded(In the Control
Panel perhaps), so it doesn't seem possible to get scan codes for every
possible Unicode char. You can however send a Unicode char by sending
WM_CHAR using the W version of SendMessage after checking that the window is
a Unicode window by calling IsWindowUnicode().
> 3) What else I've overlooked? <g>
Checking that the OS is Windows 2000 before using KEYEVENTF_UNICODE flag,
and that the minimum required OS is Windows 98 because that is when
SendInput() was introduced.
Ouch! Okay, I'll have a look at those. (I'm in the middle of some lengthy installs
at the moment, and they don't like an open browser. <groan>)
I wonder if it really matters from a SendKeys perspective, though? I mean, if you
sent a "©" to Sendkeys, it'd just use whatever codepage was in effect, no?
Shouldn't a drop-in SendKeys replacement do the same thing? (Semi-rhetorical,
granted.)
I guess I need to read those pages you cited. Thinking ahead, are you suggesting I
possibly just slip the test down to do the unicode processing for anything >= 128?
>> 2) If it's Unicode, that means we skip all the Shiftkey processing, and
>> instead just do this, right?
>
> It seems so.
I like that response. :-)
> It seems that in order to get keyboard scan codes, keyboard
> layout and support for specific code pages has to be loaded(In the Control
> Panel perhaps), so it doesn't seem possible to get scan codes for every
> possible Unicode char. You can however send a Unicode char by sending
> WM_CHAR using the W version of SendMessage after checking that the window is
> a Unicode window by calling IsWindowUnicode().
Not sure I'm following there?
>> 3) What else I've overlooked? <g>
>
> Checking that the OS is Windows 2000 before using KEYEVENTF_UNICODE flag,
> and that the minimum required OS is Windows 98 because that is when
> SendInput() was introduced.
Excellent catch(es)! Would be wise to add something like that, but I think it'd
just fail silently (except on Win95) without it, right?
Thanks much... Karl
You can always consider anything < 256 to be ANSI, which what VB's SendKeys
does. If someone wants to send Unicode characters in the range 128 to 255,
then they can change the source code by themselves.
>> It seems that in order to get keyboard scan codes, keyboard
>> layout and support for specific code pages has to be loaded(In the
>> Control
>> Panel perhaps), so it doesn't seem possible to get scan codes for every
>> possible Unicode char. You can however send a Unicode char by sending
>> WM_CHAR using the W version of SendMessage after checking that the window
>> is
>> a Unicode window by calling IsWindowUnicode().
>
> Not sure I'm following there?
I was saying that it's not always possible to get scan codes for every
character. After checking the documentation, when you use KEYEVENTF_UNICODE,
Windows sends VK_PACKET, which later translates to WM_CHAR and converted to
ANSI if the window is ANSI, so there is nothing special you need to do.
However, it seems that in certain situations the Unicode character is
discarded. Use the Search tab in MSDN and type "VK_PACKET" (5 results), or
"IME_PROP_ACCEPT_WIDE_VKEY" flag, which affect how VK_PACKET is processed.
> Would be wise to add something like that, but I think it'd just fail
> silently (except on Win95) without it, right?
You can call VB's SendKeys in Windows 9x.
Yes, unless you want to deal with codepage pecularities since Unicode
character codes 128 to 255 encode always the same characters while ANSI
character code 128 to 255 are codepage dependent.
> If code >= 0 And code < 256 Then 'ascii
Easier and presumably faster:
If Not CBool(code And &HFF00) Then
> 3) What else I've overlooked? <g>
Maybe you should check for some Unicode characters and prevent them from
beeing sent, like the
- High surrogates
D800h to DBFFh
- Low surrogates
DC00h to DFFFh
- Specials
FFF0h to FFFFh
It can't be excluded that sending one of these to a process may cause
trouble...
--
Thorsten Albers
albers (a) uni-freiburg.de
I wouldn't bother about codepage issues: You are providing an ANSI and a
Unicode version of your procedure. The ANSI procedures always sends ANSI
characters, the Unicode procedure always sends Unicode characters (even for
0-255). It's up to the developer which of the two procedures he has to
call.
? ascw(chr$(&H83&)), asc(chr$(&H83&))
402 131
Unicode character 0x0083 is a non-breaking hyphen.
The point is that "ANSI" character code 128-255 will map to a
different set of Unicode characters depending on the code page. I'm
not sure how best to test whether a character is supported on the
current code page. Maybe convert Unicode->"ANSI"->Unicode and see if
the string is unchanged?
Very good point. :-)
And the very goal of that project was to replace/replicate SendKeys.
>>> It seems that in order to get keyboard scan codes, keyboard
>>> layout and support for specific code pages has to be loaded(In the
>>> Control
>>> Panel perhaps), so it doesn't seem possible to get scan codes for every
>>> possible Unicode char. You can however send a Unicode char by sending
>>> WM_CHAR using the W version of SendMessage after checking that the window
>>> is a Unicode window by calling IsWindowUnicode().
>>
>> Not sure I'm following there?
>
> I was saying that it's not always possible to get scan codes for every
> character. After checking the documentation, when you use KEYEVENTF_UNICODE,
> Windows sends VK_PACKET, which later translates to WM_CHAR and converted to
> ANSI if the window is ANSI, so there is nothing special you need to do.
> However, it seems that in certain situations the Unicode character is
> discarded. Use the Search tab in MSDN and type "VK_PACKET" (5 results), or
> "IME_PROP_ACCEPT_WIDE_VKEY" flag, which affect how VK_PACKET is processed.
Okay, will take a look.
>> Would be wise to add something like that, but I think it'd just fail
>> silently (except on Win95) without it, right?
>
> You can call VB's SendKeys in Windows 9x.
Heh, there's a snarky workaround, alright! <bg>
Hmmmm, that's not what that code was doing, though. Rather, it was just processing
the passed string, one character at a time, and then stuffing a SendInput buffer
based on what was found. If the character was >=256, it would stuff it with a
Unicode character. If it was 0-255, it'd use the normal ANSI procedures, taking
into account things like Shift states and such.
Yikes! That's getting real ugly real fast.
Another thought would be to offer a new escape character, much like VB provides
escapes for the three common shift keys?
What's scary is Mark's example:
? ascw(chr$(&H83&)), asc(chr$(&H83&))
402 131
I guess it'll still work, though? I mean, so I get 402 instead of 131, all that
means is I'm ignoring the Shift escapes and pushing a Unicode character into the
buffer, eh?
>> If code >= 0 And code < 256 Then 'ascii
>
> Easier and presumably faster:
> If Not CBool(code And &HFF00) Then
Was gonna make sure the test was valid first, of course. He said. Heh... <g>
Yep!
>> 3) What else I've overlooked? <g>
>
> Maybe you should check for some Unicode characters and prevent them from
> beeing sent, like the
>
> - High surrogates
> D800h to DBFFh
> - Low surrogates
> DC00h to DFFFh
> - Specials
> FFF0h to FFFFh
>
> It can't be excluded that sending one of these to a process may cause
> trouble...
First I've ever heard of them! Remember, I'm USian, and therefore *highly*
unicode-impaired. :-/
After some more reading, it seems that MS introduced a way to insert
characters without having to have a keyboard scan code by adding
KEYEVENTF_UNICODE. This was probably done to support writing
pads(handwriting recognition pads). In these pads there are no keys, so
there are no scan codes. KEYEVENTF_UNICODE/VK_PACKET was introduced for this
purpose, but since "IME_PROP_ACCEPT_WIDE_VKEY" flag can affect how VK_PACKET
is processed, you can avoid VK_PACKET and send the Unicode character by
using SendUnicodeChar() function below. Windows would automatically convert
the Unicode character to ANSI if the target window is ANSI(See WM_CHAR in
MSDN for details). Note that I am using the W version of SendMessage.
Option Explicit
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" ( _
ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
lParam As Any) As Long
Private Declare Function SendMessageW Lib "user32" (ByVal hWnd As Long, _
ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Const WM_CHAR = &H102
Private Const WM_UNICHAR = &H109
' Windows 2000+ Only
Public Function SendUnicodeChar(ByVal hWnd As Long, _
ByVal lKey As Long) As Long
SendUnicodeChar = SendMessageW(hWnd, WM_CHAR, lKey, ByVal 1&)
End Function
That's what I'm doing!
> This was probably done to support writing
> pads(handwriting recognition pads). In these pads there are no keys, so
> there are no scan codes. KEYEVENTF_UNICODE/VK_PACKET was introduced for this
> purpose, but since "IME_PROP_ACCEPT_WIDE_VKEY" flag can affect how VK_PACKET
> is processed, you can avoid VK_PACKET and send the Unicode character by
> using SendUnicodeChar() function below. Windows would automatically convert
> the Unicode character to ANSI if the target window is ANSI(See WM_CHAR in
> MSDN for details). Note that I am using the W version of SendMessage.
>
>
> Option Explicit
>
> Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" ( _
> ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
> lParam As Any) As Long
> Private Declare Function SendMessageW Lib "user32" (ByVal hWnd As Long, _
> ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
> Private Const WM_CHAR = &H102
> Private Const WM_UNICHAR = &H109
>
> ' Windows 2000+ Only
> Public Function SendUnicodeChar(ByVal hWnd As Long, _
> ByVal lKey As Long) As Long
> SendUnicodeChar = SendMessageW(hWnd, WM_CHAR, lKey, ByVal 1&)
> End Function
That would prevent the mixing of character sets (to allow for stuff like navigation
keys, etc), that I was trying to support. So the question is, what advantage does
that confer over stuffing the SendInput buffer with the Unicode character?
' http://vb.mvps.org/samples/raw/MSendInput.bas.txt
Private Sub StuffBufferW(ByVal CharCode As Integer)
' Unicode is relatively simple, in this context?!
' Press and release this key.
With m_Events(m_EvtPtr)
.wVK = 0
.wScan = CharCode
.dwFlags = KEYEVENTF_UNICODE
End With
m_EvtPtr = m_EvtPtr + 1
With m_Events(m_EvtPtr)
.wVK = 0
.wScan = CharCode
.dwFlags = KEYEVENTF_UNICODE Or KEYEVENTF_KEYUP
End With
m_EvtPtr = m_EvtPtr + 1
End Sub
--
IMHO a procedure supporting Unicode should be a Unicode-only procedure.
Otherwise the result may differ from what was expected. E.g.
A) Sending character code 00C4h as Unicode
1. Receiving application does support Unicode
Application works with character code 00C4h and shows up the glyph 'A with
diaeresis above'.
That's o.k.
2. Receiving application does not support Unicode
Application works with character code C4h and shows up the glyph which in
the application's/user's/system's current ANSI codepage is encoded with
character code C4h (Western: 'A with diaresis above'; Greek: 'Delta';
Cyrillic: 'De', etc.)
That's o.k.
B) Sending character code C4h as ANSI
1. Receiving application does support Unicode
Application converts the character code from ANSI to Unicode according to
the application's/user's/system's current ANSI codepage which may be 00C4h
(Latin 'A with diaeresis above'), 0394h (Greek 'Delta'), 0414h (Cyrillic
'De'), etc.
This doesn't make much sense and presumably is not what the user of the
procedure expects!!
2. Receiving application does not support Unicode
S. A.2.
If at all, using ANSI instead of Unicode in your procedure would make sense
only if restricted to >>ASCII<< character codes (000-127) because they are
the same in any ASCII and ANSI codepage as well as in Unicode. Therefore:
If (code And &HFF80) Then
' Unicode
Else
' ANSI
End If
We all hope that this will change under a coloured president with a semitic
name who came from Indonesia... (feel free to replace 'coloured' by
whatever currently is the political correct word in the USA)
>> Hmmmm, that's not what that code was doing, though. Rather, it was just
>> processing the passed string, one character at a time, and then stuffing a
>> SendInput buffer based on what was found. If the character was >=256, it would
>> stuff it with a Unicode character. If it was 0-255, it'd use the normal ANSI
>> procedures, taking into account things like Shift states and such.
>
> IMHO a procedure supporting Unicode should be a Unicode-only procedure.
> Otherwise the result may differ from what was expected. E.g.
This is why I asked here. I'd hoped to find folks far more familiar with these
sorts of issues than I am. My first inclination was indeed to simply offer a
distinct 'W' version of the call, and leave it at that. Then, it looked "so easy!"
to get tricky and fold it all into one, that I wondered what I must be missing. Too
good to be true? Yeah, sounds like it, given what you're telling me.
So, assuming I were to create another parallel routine that's specifically intended
for Unicode... Would it also matter to the users of this routine that it support
the navigation keys as well? Or would it be sufficient to let them do navkeys with
the standard routine, then send Unicode chars with the dedicated routine?
Thanks... Karl
We all have a *lot* of hopes these days!
I'm personally very ready for change myself! :-)
The way you are doing it is the preferable way. You don't even need to worry
about ANSI<->Unicode conversion because you are using KEYEVENTF_UNICODE.
However, a while ago someone posted in a thread titled "user32.dll function
fails without any error. I am afraid it kills my business." that
KEYEVENTF_UNICODE does not work. My guess is that is due to
"IME_PROP_ACCEPT_WIDE_VKEY" flag, which effect how KEYEVENTF_UNICODE works.
In these cases sending WM_CHAR directly could solve that problem, but it
would introduce other complications because the sender need to synchronize
when the characters or control keys need to be inserted(The calls to
SendInput and SendMessageW must not interfere with each other). But this
issue seems less likely and you don't need to worry about it. If someone
says to you it doesn't work, tell them to lookup "IME_PROP_ACCEPT_WIDE_VKEY"
flag.
Heh, wow... So, there doesn't appear to be a corresponding ImmSetProperty call,
does there? <g>
I think I oughta link to this thread from the source!
Thanks... Karl
I would use Unicode only for characters (and, of course, Unicode specific
control codes). All keys not producing a character I would send as ANSI and
with their virtual VK_* key codes.
Unicode specific control codes? (Victim of my nationality... <sigh>)
> All keys not producing a character I would send as ANSI and
> with their virtual VK_* key codes.
What's the test?
For SendKeys' special keys like {F1} and everything that is specified by {}
and Shift/Alt/Ctrl, use the vbKeyXXX equivalent. For anything else, use
KEYEVENTF_UNICODE.
Okay, think I'm following. So, continue to watch for the shift key escapes?
They're only useful with the navigation keys, right? No way to flag those with
Unicode characters. Thanks!
http://rawstory.com/news/2008/Fall_from_power_Rumsfeld_relegated_to_0202.html
OMG! "... tried to ride a bus last week but failed, ..." ROTFLMAO!!! :-D
Unicode defines some, e.g. for right-to-left text processing.
The "we" in "yes, we can!" obviously has to be modified a bit. Some can not
- even if they try...
Ugh... This may end up being an "exercise left for the reader."
> Is there anyone out there who wants to use Unicode characters with the SendInput
> function? I had someone ask me recently if I could update my SendKeys replacement
> sample (http://vb.mvps.org/samples/SendInput) such that they could also send Unicode
> characters with it. I tweaked it a bit, and she reported it was now working for
> her, but I'm not sure it was a most-representative user doing the testing. I have
> no need (or interest) in using that functionality myself, so I'm not sure if my
> assumptions were good for others. Anyone wanna have a crack at it?
> --
> ..NET: It's About Trust!
> http://vfred.mvps.org
>
>
>
Does anyone know why apps running in a DOS window will ignore SendInput with
KEYEVENTF_UNICODE?
I can send chars to the DOS prompt, but if I start "edit", all chars are
ignored.
Thanks for any help,
Tony
Before sending the key input to a window check by a call to
IsWindowUnicode(), if the window is Unicode enabled at all. If it is not,
it will not handle Unicode input and messages in any case. If it is, it
might be possible that it supports Unicode input and messages.
Thanks for the quick reply.
The window in question is the Command Prompt on XP. It does return TRUE to
IsWindowUnicode, and it works fine. The problem is launching an app within
the Command Prompt window, like "edit".
Once "edit" is running, all keystrokes are ignored.
Does anyone know why?
Presumably because 'Edit' is not Unicode-enabled? Try to load a Unicode
text in edit and see what happens.