Solved

Scancode to ASCII with WinAPI ToASCIIEx().

Posted on 2000-04-25
7
1,742 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

Independent Software Vendors: 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!

Question has a verified solution.

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

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
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…
This video Micro Tutorial shows how to password-protect PDF files with free software. Many software products can do this, such as Adobe Acrobat (but not Adobe Reader), Nuance PaperPort, and Nuance Power PDF, but they are not free products. This vide…
In this video, viewers are given an introduction to using the Windows 10 Snipping Tool, how to quickly locate it when it's needed and also how make it always available with a single click of a mouse button, by pinning it to the Desktop Task Bar. Int…

724 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