Solved

Scancode to ASCII with WinAPI ToASCIIEx().

Posted on 2000-04-25
7
1,725 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…

737 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