Solved

Scancode to ASCII with WinAPI ToASCIIEx().

Posted on 2000-04-25
7
1,695 Views
Last Modified: 2008-02-20
Okay, the subject says it all.  Given a scancode, I want to get the ASCII code of the key pressed.  The following function should do it, but I think I'm having a problem with a pointer.

function ScanToASCII(scancode: DWORD; PResult: PChar): Integer;
var
  KBLayout: HKL;
  KBState: TKeyboardState;
  vk: UINT;
begin
  KBLayout := GetKeyboardLayout(0);

  if (GetKeyboardState(KBState) = False) then
  begin
    Result := 0;
    exit;
  end;

  vk := MapVirtualKeyEx(scancode, 1, KBLayout);

  Result := ToAsciiEx(vk, scancode, KBState, PResult, 0, KBLayout);
end;

The above function is my conversion of the C function found at http://www.gamedev.net/reference/programming/directx/article842.asp.  I'm thinking that there's a problem with my usage of "PResult PChar" in place of the C function's "ushort* result" in the calling parameter list, but I can't seem to get it right.  Any thoughts?
0
Comment
Question by:Traal
  • 3
  • 3
7 Comments
 
LVL 3

Expert Comment

by:shenqw
ID: 2750093
function ScanToASCII(scancode: DWORD; var PResult: PChar): Integer;
var
  KBLayout: HKL;
  KBState: TKeyboardState;
  vk: UINT;
begin
  KBLayout := GetKeyboardLayout(0);

  if (GetKeyboardState(KBState) = False) then
  begin
    Result := 0;
    exit;
  end;

  vk := MapVirtualKeyEx(scancode, 1, KBLayout);

  Result := ToAsciiEx(vk, scancode, KBState, PResult, 0, KBLayout);
end;


Call the function:

var
  P:PChar;
begin
  GetMem(P,256);
  //ScanToASCII(...,P);
  FreeMem(P,256);
end;
0
 
LVL 10

Expert Comment

by:Lischke
ID: 2750470
Traal,

you have overseen a small point which is important. The PResult parameter must be PWideChar (in C it is a pointer to an unsigned short, which is Word in Delphi).

Additionally, the previous allocation of memory is not necessary. There can only be at most two characters in the result buffer, so recommend to write the code so:

function ScanToASCII(scancode: DWORD; var ASCIICodes: PWideChar): Integer;
var
  KBLayout: HKL;
  KBState: TKeyboardState;
  vk: UINT;
begin
  KBLayout := GetKeyboardLayout(0);

  if (GetKeyboardState(KBState) = False) then
  begin
    Result := 0;
    exit;
  end;

  vk := MapVirtualKeyEx(scancode, 1, KBLayout);

  Result := ToAsciiEx(vk, scancode, KBState, ASCIICodes, 0, KBLayout);
end;

and to call it:

var
  Codes: array[0..1] of WideChar;

begin
  ScanToASCII(..., @Codes);
end;

Ciao, Mike
0
 

Author Comment

by:Traal
ID: 2750879
Okay, Lischke, I made the change to PWIdeChar, and now I get the following error message when compiling:

"Incompatible types:  WideChar and Char".

The error occurs here...

"Result := ToAsciiEx(vk, scancode, KBState, ASCIICodes, 0, KBLayout);"

....with the cursor right after ASCIICodes.  So, it seems to be asking for a Char instead of a WideChar.

Brian
0
Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

 
LVL 10

Accepted Solution

by:
Lischke earned 50 total points
ID: 2750922
Mmh, MSDN states the parameter is a PWord while Delphi's translation is a PChar. From this I conclude the C definition is (how seldom!) really a pointer to a Word instead an array of Words (because there are at most two characters to return).

In this case your code should work fine. I have no idea why it doesn't. What is actually wrong?

Passing the parameter by reference is basically not necessary because you will not change the pointer but to what it points to. The code looks then (very much like your original):

function ScanToASCII(scancode: DWORD; ASCIICodes: PChar): Integer;
var
  KBLayout: HKL;
  KBState: TKeyboardState;
  vk: UINT;
begin
  KBLayout := GetKeyboardLayout(0);

  if (GetKeyboardState(KBState) = False) then
  begin
    Result := 0;
    exit;
  end;

  vk := MapVirtualKeyEx(scancode, 1, KBLayout);

  Result := ToAsciiEx(vk, scancode, KBState, ASCIICodes, 0, KBLayout);
end;

var
  Codes: array[0..1] of Char;

begin
  ScanToASCII(..., @Codes);
end;


If this does still not work then please tell us more detailed what happens.

Ciao, Mike
0
 

Author Comment

by:Traal
ID: 2751258
Adjusted points from 40 to 50
0
 

Author Comment

by:Traal
ID: 2751259
Success!  I didn't have the Codes buffer set up properly, and also wasn't calling ScanToASCII with the address (@) of the buffer.  Simple errors!  Sheesh!  Thanks for your excellent help.

Brian
0
 
LVL 10

Expert Comment

by:Lischke
ID: 2751275
:-))
0

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This Micro Tutorial will give you a basic overview how to record your screen with Microsoft Expression Encoder. This program is still free and open for the public to download. This will be demonstrated using Microsoft Expression Encoder 4.

832 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question