☆フリガナの取得 その2

フリガナの取得 その1 のコードをWindowsフォームアプリケーションでも作ってみました。

unit WinForm;

interface

uses
 System.Drawing, System.Collections, System.ComponentModel,
 System.Windows.Forms, System.Data, System.Runtime.InteropServices,
 System.Text;

type
 TextBoxEx = class;

 TWinForm = class(System.Windows.Forms.Form)
 {$REGION 'デザイナ管理コード'}
 strict private
  /// 
  /// 必要なデザイナ変数です。
  /// 
  Components: System.ComponentModel.Container;
  /// 
  /// デザイナサポートに必要なメソッドです。
  /// このメソッドの内容をコードエディタで変更しないでください。
  /// 
  procedure InitializeComponent;
 {$ENDREGION}
 strict protected
  /// 
  /// 使用されているリソースの後処理を実行します。
  /// 
  procedure Dispose(Disposing: Boolean); override;
 private
  TextBox1: TextBox;
  TextBoxEx1: TextBoxEx;
  procedure OnCompositionStr(Sender: TObject; Value: String);
 public
  constructor Create;
 end;

 TCompositionStrEvent = procedure (Sender: TObject; Value: String) of Object;

 TextBoxEx = class(TextBox)
 private
  FOnCompositionStr: TCompositionStrEvent;
 strict protected
  procedure WndProc(var M: Message); override;
 published
  property OnCompositionStr: TCompositionStrEvent
   read FOnCompositionStr write FOnCompositionStr;
 end;

 [assembly: RuntimeRequiredAttribute(TypeOf(TWinForm))]

implementation

{$AUTOBOX ON}

{$REGION 'Windows フォームデザイナが生成したコード'}
/// 
/// デザイナサポートに必要なメソッドです。
/// このメソッドの内容をコードエディタで変更しないでください。
/// 
procedure TWinForm.InitializeComponent;
begin
 // 
 // TWinForm
 // 
 Self.AutoScaleBaseSize := System.Drawing.Size.Create(5, 12);
 Self.ClientSize := System.Drawing.Size.Create(292, 266);
 Self.Name := 'TWinForm';
 Self.Text := 'WinForm';
end;
{$ENDREGION}

type
 HIMC = Integer;

const
 GCS_RESULTREADSTR = $0200;
 WM_IME_COMPOSITION = $010F;

[DllImport('Imm32.dll')]
function ImmGetContext(hWnd: IntPtr): HIMC; external;

[DllImport('Imm32.dll')]
function ImmGetCompositionString(hImc: HIMC; dWord1: Integer;
lpBuf: StringBuilder; dwBufLen: Integer): Longint; external;

[DllImport('Imm32.dll')]
function ImmReleaseContext(hWnd: IntPtr; hImc: HIMC): Boolean; external;

procedure TextBoxEx.WndProc(var M: Message);
var
 Imc: HIMC;
 Len: Longint;
 Str: StringBuilder;
 Temp1, Temp2: array of Byte;
begin
 if Assigned(FOnCompositionStr) and (M.Msg = WM_IME_COMPOSITION) and
  ((Integer(M.LParam) and GCS_RESULTREADSTR) <> 0) then
 begin
  Imc := ImmGetContext(Self.Handle);
  Len := ImmGetCompositionString(Imc, GCS_RESULTREADSTR, nil, 0);

  Str := StringBuilder.Create(Len);
  ImmGetCompositionString(Imc, GCS_RESULTREADSTR, Str, Str.Capacity);
  ImmReleaseContext(Self.Handle, Imc);

  Temp1 := System.Text.Encoding.Default.GetBytes(Str.ToString);
  SetLength(Temp2, Len);
  System.Array.Copy(Temp1, 0, Temp2, 0, Len);

  FOnCompositionStr(Self, System.Text.Encoding.Default.GetString(Temp2));
 end;

 inherited WndProc(M);
end;



procedure TWinForm.Dispose(Disposing: Boolean);
begin
 if Disposing then
 begin
  if Components <> nil then
   Components.Dispose();
 end;
 inherited Dispose(Disposing);
end;

constructor TWinForm.Create;
begin
 inherited Create;
 //
 // Windows Form デザイナのサポートに必要です。
 //
 InitializeComponent;
 //
 // TODO: InitializeComponent 呼び出しの後のコンストラクタコードを追加
 //

 { EditEx1の生成 }
 TextBoxEx1 := TextBoxEx.Create;
 TextBoxEx1.Parent := Self;
 TextBoxEx1.Top := 10;
 TextBoxEx1.Left := 10;
 TextBoxEx1.Text := 'ここに入力して!';
 TextBoxEx1.OnCompositionStr := OnCompositionStr;

 { Edit1の生成 }
 TextBox1 := TextBox.Create;
 TextBox1.Parent := Self;
 TextBox1.Name := 'Edit1';
 TextBox1.Top := 40;
 TextBox1.Left := 10;
 TextBox1.Text := '';
end;

procedure TWinForm.OnCompositionStr(Sender: TObject; Value: String);
begin
 TextBox1.Text := TextBox1.Text + Value;
end;
end.

|

☆フリガナの取得 その1

.NETで入力した時のフリガナを取得するには、どうしたらいいのかといろいろ探しましたが、結局Win32のDLLを利用する方法しか見つけられませんでした。
以下、GotDotNet Japan 掲示板 での kazuMorono2 さんのコメントを参考に作ったものです。
http://www.gdncom.jp/general/bbs/ShowPost.aspx?PostID=21415
ここでは、Delphi for .NETで作成しました。一応、動作しているようです。

unit unit1;

interface

uses
 Windows, Messages, SysUtils, variants, classes, Graphics, Controls, Forms,
 Dialogs,
 System.Runtime.InteropServices, System.Text, Borland.Vcl.WinUtils,
 System.ComponentModel, Borland.Vcl.StdCtrls;

type
 TCompositionStrEvent = procedure (Sender: TObject; Value: String) of Object;

 TEditEx = class(TEdit)
 private
  FOnCompositionStr: TCompositionStrEvent;
 protected
  procedure WndProc(var Message: TMessage); override;
 published
  property OnCompositionStr: TCompositionStrEvent
   read FOnCompositionStr write FOnCompositionStr;
 end;

 TForm1 = class(TForm)
  procedure FormCreate(Sender: TObject);
 private
  Edit1: TEdit;
  EditEx1: TEditEx;
  procedure OnCompositionStr(Sender: TObject; Value: String);
 end;

var
 Form1: TForm1;

implementation

{$R *.nfm}

{ Borland.Vcl.Imm の ImmGetCompositionStringを使うとWindows XPの場合、
 戻り値が2倍になるため、Borland.Vcl.Immを使わず、ここで定義しておく。 
 たぶんCharSetの指定が原因だと思われる。}

type
 HIMC = Integer;

const
 GCS_RESULTREADSTR = $0200;

[DllImport('Imm32.dll')]
function ImmGetContext(hWnd: HWND): HIMC; external;

[DllImport('Imm32.dll')]
function ImmGetCompositionString(hImc: HIMC; dWord1: DWORD;
lpBuf: StringBuilder; dwBufLen: DWORD): Longint; external;

[DllImport('Imm32.dll')]
function ImmReleaseContext(hWnd: HWND; hImc: HIMC): Boolean; external;


procedure TEditEx.WndProc(var Message: TMessage);
var
 Imc: HIMC;
 Len: Longint;
 Str: StringBuilder;
 Temp1, Temp2: array of Byte;
begin
 if Assigned(FOnCompositionStr) and (Message.Msg = WM_IME_COMPOSITION) and
  ((Message.LParam and GCS_RESULTREADSTR) <> 0) then
 begin
  Imc := ImmGetContext(Self.Handle);
  Len := ImmGetCompositionString(Imc, GCS_RESULTREADSTR, nil, 0);

  Str := StringBuilder.Create(Len);
  ImmGetCompositionString(Imc, GCS_RESULTREADSTR, Str, Str.Capacity);
  ImmReleaseContext(Self.Handle, Imc);

  Temp1 := System.Text.Encoding.Default.GetBytes(Str.ToString);
  SetLength(Temp2, Len);
  System.Array.Copy(Temp1, 0, Temp2, 0, Len);

  FOnCompositionStr(Self, System.Text.Encoding.Default.GetString(Temp2));
 end;

 inherited WndProc(Message);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 { EditEx1の生成 }
 EditEx1 := TEditEx.Create(Self);
 EditEx1.Parent := Self;
 EditEx1.Top := 10;
 EditEx1.Left := 10;
 EditEx1.Text := 'ここに入力して!';

 EditEx1.OnCompositionStr := OnCompositionStr;
 { Edit1の生成 }
 Edit1 := TEdit.Create(Self);
 Edit1.Parent := Self;
 Edit1.Top := 40;
 Edit1.Left := 10;
 Edit1.Text := '';
end;

procedure TForm1.OnCompositionStr(Sender: TObject; Value: String);
begin
 Edit1.Text := Edit1.Text + Value;
end;

end.

|