0

我正在使用此代码将虚拟键转换为 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; 

它在我的电脑上运行良好,但在中国电脑上我得到了这个:

富

它将中文字符转换为汉语拼音。我认为该函数实际上返回了键盘的原始输入,而不是用户实际想要输入的内容。

我该如何处理?

4

2 回答 2

2

根据评论,这是一个示例,说明如何通过处理KeyPress事件而不是手动转换KeyDown事件来避免问题。TNT 控件不提供WideChar KeyPress事件,但添加起来相当容易。理想情况下,您不应该像我在这里所做的那样将扩展放入派生类中TTntMemoTTntForm而是修改 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.
于 2012-06-05T21:38:50.383 回答
1

我也没有太多输入中文的经验,但我怀疑这是IME(输入法编辑器)在起作用。这就是允许中国用户输入拼音的原因,然后将其翻译成表意字符(否则,你'我需要一个有 1000 多个键的键盘......)

虚拟键码与键盘直接相关,因此必然只对应于输入的键。所以你的函数工作正常:它将 VKEY 代码转换为 WideChar。为了做你想做的事,你必须编写第二个函数,它将拼音转换为字符。

如果你想专门为中文做这个,我敢打赌那里有做这个的功能。如果你想让它更通用,并且独立于语言环境和语言,那么也许可以为相关的 TMemo 与 IME 交互,但如果是这样,我不知道。我最好的猜测是在MSDN 中搜索 IME

但是,为了回应hvd 的评论:你想在这里完成什么?

只复制 TMemo 的文本不是更容易吗?

于 2012-06-05T07:01:07.040 回答