Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

PostKeyEx(P.Below) not working correctly

122 views
Skip to first unread message

Paul

unread,
Sep 11, 2005, 11:11:54 AM9/11/05
to
Hi all,

I'm using P. Belows' s code to send a keystroke to another computer on our
LAN.

It works fine when the keystroke in sent to another PC with the same
keyboard layout.
The are several users here using a keyboard with a French keyb layout , and
they receive wrong characters.
The characters 'a' .. 'z' and ' .. 'Z' appear correct on the remote PC, the
rest is completely wrong.
I've tried changing the uMapType in the MapVirtualKey proc, but it doesn't
help much.
Is there anyone who knows how to solve this ?

TIA
Paul,

PS : I'm using a std US keyboard myself.

procedure PostKeyEx32(key: Word; const shift: TShiftState; specialkey:
Boolean);
{************************************************************
* Procedure PostKeyEx32
*
* Parameters:
* key : virtual keycode of the key to send. For printable
* keys this is simply the ANSI code (Ord(character)).
* shift : state of the modifier keys. This is a set, so you
* can set several of these keys (shift, control, alt,
* mouse buttons) in tandem. The TShiftState type is
* declared in the Classes Unit.
* specialkey: normally this should be False. Set it to True to
* specify a key on the numeric keypad, for example.
* Description:
* Uses keybd_event to manufacture a series of key events matching
* the passed parameters. The events go to the control with focus.
* Note that for characters key is always the upper-case version of
* the character. Sending without any modifier keys will result in
* a lower-case character, sending it with [ssShift] will result
* in an upper-case character!
// Code by P. Below
************************************************************}
type
TShiftKeyInfo = record
shift: Byte;
vkey: Byte;
end;
byteset = set of 0..7;
const
shiftkeys: array [1..3] of TShiftKeyInfo =
((shift: Ord(ssCtrl); vkey: VK_CONTROL),
(shift: Ord(ssShift); vkey: VK_SHIFT),
(shift: Ord(ssAlt); vkey: VK_MENU));
var
flag: DWORD;
bShift: ByteSet absolute shift;
i: Integer;
begin
for i := 1 to 3 do
begin
if shiftkeys[i].shift in bShift then
keybd_event(shiftkeys[i].vkey, MapVirtualKey(shiftkeys[i].vkey, 0), 0,
0);
end; { For }
if specialkey then
flag := KEYEVENTF_EXTENDEDKEY
else
flag := 0;

keybd_event(key, MapvirtualKey(key, 0), flag, 0);
flag := flag or KEYEVENTF_KEYUP;
keybd_event(key, MapvirtualKey(key, 0), flag, 0);

for i := 3 downto 1 do
begin
if shiftkeys[i].shift in bShift then
keybd_event(shiftkeys[i].vkey, MapVirtualKey(shiftkeys[i].vkey, 0),
KEYEVENTF_KEYUP, 0);
end; { For }
end; { PostKeyEx32 }

Peter Below (TeamB)

unread,
Sep 11, 2005, 6:10:35 PM9/11/05
to
In article <432448ef$1...@newsgroups.borland.com>, Paul wrote:
> I'm using P. Belows' s code to send a keystroke to another computer on our
> LAN.

How do you do that? KeybdEvent is a local function.

Anyway, you may be passing the wrong virtual key codes. If you want to send
text, try this wrapper function:

Procedure SendText( S: String );
Procedure SendRawCharacter( ch : Char );
Var
i: Integer;
numStr: String;
Begin
numStr := Format('%4.4d',[Ord(ch)]);
keybd_event( VK_MENU, MapVirtualKey(VK_MENU, 0),
0, 0);
for i:= 1 to Length(numStr) do
PostKeyEx32( VK_NUMPAD0 + Ord(numstr[i])-Ord('0'), [], false );
keybd_event( VK_MENU, MapVirtualKey(VK_MENU, 0),
KEYEVENTF_KEYUP, 0);
End;

Var
flags: TShiftState;
vcode: word;
ret : word;
i, n : Integer;
mask : word;
Begin { SendText }
For i := 1 To Length(S) Do Begin
ret := VkKeyScan( S[i] );
If ret = $FFFF Then
SendRawCharacter( S[i] )
Else Begin
vcode := Lobyte( ret );
flags := [];
mask := $100;
For n := 1 To 3 Do Begin
If (ret and mask) <> 0 Then Begin
Case mask Of
$100: Include( flags, ssShift );
$200: Include( flags, ssCtrl );
$400: Include( flags, ssAlt );
End; { Case }
End; { If }
mask := mask shl 1;
End; { For }
PostKeyEx32( vcode, flags, false );
End; { Else }
End; { For }
End; { SendText }

--
Peter Below (TeamB)
Use the newsgroup archives :
http://www.mers.com/searchsite.html
http://www.tamaracka.com/search.htm
http://groups.google.com
http://www.prolix.be


Jim P

unread,
Sep 11, 2005, 10:25:23 PM9/11/05
to
I would expect the problem to be in the way windows handles different
Keyboards and languages. You might have to add a table on the receiving
side or sending to cause the key codes to be translated as needed.

I know for Bulgarian. The same keyboard was used - just the key
assignments were changed and the characters related to the keys.

The fonts have many parts to them besides the standard ASCII characters
- - and I do not fully understand all of the font aspects but this again
forms part of the issue. Using a French based Font instead of English
would have different looking character for the same character position
and this could be the problem.

Jim P.

Paul

unread,
Sep 12, 2005, 12:41:15 PM9/12/05
to
>How do you do that? KeybdEvent is a local function.

I just use the forms OnKeyUp event and send it to the remote PC using TCP
Each character is immediately sent.
I works fine if the remote PC also has a std US keyboard (as I have).
It just goes wrong if the remote PC has a French keyboard (azerty).


Paul

"Peter Below (TeamB)" <10011...@compuXXserve.com> schreef in bericht
news:VA.0000bfd...@nomail.please...

Peter Below (TeamB)

unread,
Sep 14, 2005, 5:12:12 PM9/14/05
to
In article <4325...@newsgroups.borland.com>, Paul wrote:
> >How do you do that? KeybdEvent is a local function.
>
> I just use the forms OnKeyUp event and send it to the remote PC using TCP
> Each character is immediately sent.

And the remote PC then calls keybd_event, i take it?

Your problem is that you are using OnKeyUp, which gets you virtual key
codes, not characters. The same virtual key codes will yield different
characters on different keyboard layouts for some keys. In fact even the
same character codes may yield different characters if your remote PC uses a
different standard code page from yours (which it well may do if it uses a
different locale setting).

So the only reliable solution i see (especially if you do not know which
locale/keyboard the remote PC will be using) is to

- on the source PC trap the WM_KEYDOWN message, e.g. in
Application.OnMessage. You need the message lparam the key events do
not surface.

- call the ToUnicode method to try to convert the key code to a Unicode
character. This may fail if the key code is not for a key that produces
a character.

- send the virtual key code *or* the unicode character to the remote PC,
with info on what you send, so the other side knows how to handle it.

- on the receiver side handle received key codes like you do now, but
for characters you need to use the Unicode equivalent of the SendText
function i posted in the last reply, using VKKeyScanW instead of
VKKeyScan.

This scheme should work on NT platforms (NT4, Win2K, XP, Win2003) but it
will likely not work in Win9x. If you only ever expect to pass ASCII text in
the 7 bit range you can just replace ToUnicode with ToAscii and send Ascii
characters instead of Unicode characters. In this case you can use the
SendText function as posted to launch the received characters on the
receiver PC. But the key is that you have to handle keys that produce
characters differently from those that do not produce characters, since the
mapping of the former to characters is locale-dependent.

0 new messages