我正在使用此代码将虚拟键转换为WideString:
function VKeytoWideString (Key : Word) : WideString;
var
WBuff : array [0..255] of WideChar;
KeyboardState : TKeyboardState;
UResult : Integer;
begin
Result := '';
GetKeyBoardState (KeyboardState);
ZeroMemory(@WBuff[0], SizeOf(WBuff));
UResult := ToUnicode(key, MapVirtualKey(key, 0), KeyboardState, WBuff, Length(WBuff), 0);
if UResult > 0 then
SetString(Result, WBuff, UResult)
else if UResult = -1 then
Result := WBuff;
end;
它在我的电脑上工作正常,但在中国电脑上我得到了这个:
foo http://img341.imageshack.us/img341/9506/clipboard01l.png
它将中国字符转换为汉语拼音。我认为该函数实际上返回键盘的原始输入而不是用户实际想要输入的内容。
我该如何处理?
答案 0 :(得分:2)
根据评论,以下是一个示例,说明如何通过处理KeyPress
事件而不是手动转换KeyDown
事件来避免此问题。 TNT控件不提供WideChar
KeyPress
事件,但添加相当容易。理想情况下,您不应该像我在这里所做的那样将扩展名TTntMemo
和TTntForm
放在派生类中,而是修改TNT源代码。
表单包含两个TTntMemo
控件。在第一个按键将在第二个中记录事件。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, TntForms, StdCtrls, TntStdCtrls;
type
TKeyPressWEvent = procedure(Sender: TObject; var Key: WideChar) of object;
TTntMemo = class(TntStdCtrls.TTntMemo)
private
FOnKeyPressW: TKeyPressWEvent;
procedure WMChar(var Msg: TWMChar); message WM_CHAR;
protected
function DoKeyPressW(var Message: TWMKey): Boolean;
procedure KeyPressW(var Key: WideChar);
published
property OnKeyPressW: TKeyPressWEvent read FOnKeyPressW write FOnKeyPressW;
end;
TTntForm = class(TntForms.TTntForm)
private
FOnKeyPressW: TKeyPressWEvent;
procedure WMChar(var Msg: TWMChar); message WM_CHAR;
protected
function DoKeyPressW(var Message: TWMKey): Boolean;
procedure KeyPressW(var Key: WideChar);
published
property OnKeyPressW: TKeyPressWEvent read FOnKeyPressW write FOnKeyPressW;
end;
TForm1 = class(TTntForm)
TntMemo1: TTntMemo;
TntMemo2: TTntMemo;
procedure FormCreate(Sender: TObject);
procedure FormKeyPressW(Sender: TObject; var Key: WideChar);
procedure TntMemo1KeyPressW(Sender: TObject; var Key: WideChar);
end;
var
Form1: TForm1;
implementation
uses
TntControls;
{$R *.dfm}
type
TWinControlAccess = class(TWinControl);
TTntFormAccess = class(TTntForm);
function TntControl_DoKeyPressW(Self: TWinControl; var Message: TWMKey;
KeyPressW: Pointer): Boolean;
type
TKeyPressWProc = procedure(Self: TWinControl; var Key: WideChar);
var
Form: TCustomForm;
Ch: WideChar;
begin
Result := True;
Form := GetParentForm(Self);
if (Form <> nil) and (Form <> Self) and Form.KeyPreview then
begin
if (Form is TTntForm) and TTntFormAccess(Form).DoKeyPressW(Message) then Exit;
if TWinControlAccess(Form).DoKeyPress(Message) then Exit;
end;
if not (csNoStdEvents in Self.ControlStyle) then
begin
Ch := GetWideCharFromWMCharMsg(Message);
TKeyPressWProc(KeyPressW)(Self, Ch);
SetWideCharForWMCharMsg(Message, Ch);
if Ch = #0 then Exit;
end;
Result := False;
end;
{ TTntMemo }
function TTntMemo.DoKeyPressW(var Message: TWMKey): Boolean;
begin
Result := TntControl_DoKeyPressW(Self, Message, @TTntMemo.KeyPressW);
end;
procedure TTntMemo.KeyPressW(var Key: WideChar);
begin
if Assigned(FOnKeyPressW) then FOnKeyPressW(Self, Key);
end;
procedure TTntMemo.WMChar(var Msg: TWMChar);
begin
if not DoKeyPressW(Msg) then inherited;
end;
{ TTntForm }
function TTntForm.DoKeyPressW(var Message: TWMKey): Boolean;
begin
Result := TntControl_DoKeyPressW(Self, Message, @TTntForm.KeyPressW);
end;
procedure TTntForm.KeyPressW(var Key: WideChar);
begin
if Assigned(FOnKeyPressW) then FOnKeyPressW(Self, Key);
end;
procedure TTntForm.WMChar(var Msg: TWMChar);
begin
if not DoKeyPressW(Msg) then inherited;
end;
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.OnKeyPressW := FormKeyPressW;
TntMemo1.OnKeyPressW := TntMemo1KeyPressW;
end;
procedure TForm1.FormKeyPressW(Sender: TObject; var Key: WideChar);
begin
TntMemo2.Lines.Add(WideString('FormKeyPress: ') + Key);
end;
procedure TForm1.TntMemo1KeyPressW(Sender: TObject; var Key: WideChar);
begin
TntMemo2.Lines.Add(WideString('TntMemo1KeyPress: ') + Key);
end;
end.
答案 1 :(得分:1)
我也没有太多打字中文的经验,但我怀疑这是IME(输入法编辑器)的开头。这就是中国用户输入拼音的原因,然后将其翻译成表意字符(否则,你需要一个带有1000多个键的键盘......)
虚拟键码与键盘直接相关,因此必然只对应于输入的键。所以你的函数工作正常:它将VKEY代码转换为WideChar。要做你想做的事,你必须写第二个函数,它将拼音转换为字符。
如果你想专门为中国人做这件事,我敢打赌那里有这样做的功能。如果你想使它更通用,并且独立于语言环境和语言,那么也许可以与相关TMemo的IME接口,但如果是这样,我还没有得到线索。我最好的猜测是search MSDN for IME。
但是,回应hvd’s comment:你想在这里完成什么?
复制TMemo的文本会不会更容易?