タッチキーボード(スクリーンキーボード,ソフトウェアキーボード)を作成 ~Delphiソースコード集
日本語のタッチキーボード(スクリーンキーボード,ソフトウェアキーボード)を作成します。
タッチキーボードを作成するにはCreateParamsをオーバーライドしてウィンドウがフォーカスを持たないようにする必要があります。
また、使用するコントロールもフォーカスを持たないもの(TSpeedButtonやTBitBtnなど)を使う必要があります。
uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs , Vcl.Buttons; type TForm1 = class(TForm) private { Private 宣言 } protected procedure CreateParams(var Params: TCreateParams); override; public { Public 宣言 } end; implementation {$R *.dfm} procedure TForm1.CreateParams(var Params: TCreateParams); begin inherited; Params.ExStyle := (Params.ExStyle or WS_EX_NOACTIVATE //アクティブにならないウィンドウ or WS_EX_TOPMOST //常に手前に配置 ) // and (not WS_EX_APPWINDOW) //タスクバーに配置しない ; end;
キーボードのキーを押すには「keybd_event」API関数を使用します。
procedure keybd_event(bVk: Byte; bScan: Byte; dwFlags: DWORD; dwExtraInfo: UIntPtr); stdcall;
プロジェクトの作成と画面設計
[ファイル]⇒[新規作成]⇒[VCL フォーム アプリケーション -Delphi]をクリックし、新規プロジェクトを作成します。
画面設計は完了です。
ソースコードの記述
キーボードから「F12」キーを押してコードエディタに切り替えます。
以下ソースコードをコピー&ペーストして貼り付けます。
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs , Vcl.Buttons; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); private { Private 宣言 } IsShift:Boolean; procedure BtnClick(Sender: TObject); procedure SetKeyBoard(); protected procedure CreateParams(var Params: TCreateParams); override; public { Public 宣言 } end; TVKeybd=record C,S:String; K:Byte; W:Integer; SB:TSpeedButton; end; var Form1: TForm1; kbd : array[0..5] of array[0..14] of TVKeybd = ( ( (C:'ESC'; S:'ESC'; K:VK_ESCAPE; W:60), (C:'F1'; S:'F1'; K:VK_F1; W:60), (C:'F2'; S:'F2'; K:VK_F2; W:60), (C:'F3'; S:'F3'; K:VK_F3; W:60), (C:'F4'; S:'F4'; K:VK_F4; W:60), (C:'F5'; S:'F5'; K:VK_F5; W:60), (C:'F6'; S:'F6'; K:VK_F6; W:60), (C:'F7'; S:'F7'; K:VK_F7; W:60), (C:'F8'; S:'F8'; K:VK_F8; W:60), (C:'F9'; S:'F9'; K:VK_F9; W:60), (C:'F10'; S:'F10'; K:VK_F10; W:60), (C:'F11'; S:'F11'; K:VK_F11; W:60), (C:'F12'; S:'F12'; K:VK_F12; W:60), (C:'Prt'; S:'Prt'; K:VK_SNAPSHOT; W:60), (C:''; S:''; K:0; W:0) ),( (C:'漢字'; S:'漢字'; K:255; W:60), (C:'1'; S:'!'; K:Ord('1'); W:60), (C:'2'; S:'"'; K:Ord('2'); W:60), (C:'3'; S:'#'; K:Ord('3'); W:60), (C:'4'; S:'$'; K:Ord('4'); W:60), (C:'5'; S:'%'; K:Ord('5'); W:60), (C:'6'; S:'&&'; K:Ord('6'); W:60), (C:'7'; S:''''; K:Ord('7'); W:60), (C:'8'; S:'('; K:Ord('8'); W:60), (C:'9'; S:')'; K:Ord('9'); W:60), (C:'0'; S:''; K:Ord('0'); W:60), (C:'-'; S:'='; K:VK_OEM_MINUS; W:60), (C:'^'; S:'~'; K:VK_OEM_7; W:60), (C:'\'; S:'|'; K:VK_OEM_5; W:60), (C:'BS'; S:'BS'; K:VK_BACK; W:60) ),( (C:'Tab'; S:'Tab'; K:VK_TAB; W:60), (C:'q'; S:'Q'; K:Ord('Q'); W:60), (C:'w'; S:'W'; K:Ord('W'); W:60), (C:'e'; S:'E'; K:Ord('E'); W:60), (C:'r'; S:'R'; K:Ord('R'); W:60), (C:'t'; S:'T'; K:Ord('T'); W:60), (C:'y'; S:'Y'; K:Ord('Y'); W:60), (C:'u'; S:'U'; K:Ord('U'); W:60), (C:'i'; S:'I'; K:Ord('I'); W:60), (C:'o'; S:'O'; K:Ord('O'); W:60), (C:'p'; S:'P'; K:Ord('P'); W:60), (C:'@'; S:'`'; K:VK_OEM_3; W:60), (C:'['; S:'{'; K:VK_OEM_4; W:60), (C:'Ent'; S:'Ent'; K:VK_RETURN; W:120), (C:''; S:''; K:0; W:0) ),( (C:'Cap'; S:'Cap'; K:VK_CAPITAL; W:60), (C:'a'; S:'A'; K:Ord('A'); W:60), (C:'s'; S:'S'; K:Ord('S'); W:60), (C:'d'; S:'D'; K:Ord('D'); W:60), (C:'f'; S:'F'; K:Ord('F'); W:60), (C:'g'; S:'G'; K:Ord('G'); W:60), (C:'h'; S:'H'; K:Ord('H'); W:60), (C:'j'; S:'J'; K:Ord('J'); W:60), (C:'k'; S:'K'; K:Ord('K'); W:60), (C:'l'; S:'L'; K:Ord('L'); W:60), (C:';'; S:'+'; K:VK_OEM_PLUS; W:60), (C:':'; S:'*'; K:VK_OEM_1; W:60), (C:']'; S:'}'; K:VK_OEM_6; W:60), (C:''; S:''; K:0; W:0), (C:''; S:''; K:0; W:0) ),( (C:'Shift'; S:'Shift'; K:VK_SHIFT; W:60), (C:'z'; S:'Z'; K:Ord('Z'); W:60), (C:'x'; S:'X'; K:Ord('X'); W:60), (C:'c'; S:'C'; K:Ord('C'); W:60), (C:'v'; S:'V'; K:Ord('V'); W:60), (C:'b'; S:'B'; K:Ord('B'); W:60), (C:'n'; S:'N'; K:Ord('N'); W:60), (C:'m'; S:'M'; K:Ord('M'); W:60), (C:','; S:'<'; K:VK_OEM_COMMA; W:60), (C:'.'; S:'>'; K:VK_OEM_PERIOD; W:60), (C:'/'; S:'?'; K:VK_OEM_2; W:60), (C:'\'; S:'_'; K:VK_OEM_102; W:60), (C:''; S:''; K:0; W:0), (C:''; S:''; K:0; W:0), (C:''; S:''; K:0; W:0) ),( (C:'Del'; S:'Del'; K:VK_DELETE; W:60), (C:'Ins'; S:'Ins'; K:VK_INSERT; W:60), (C:'Space'; S:'Space'; K:VK_SPACE; W:180), (C:'←'; S:'←'; K:VK_LEFT; W:60), (C:'↑'; S:'↑'; K:VK_UP; W:60), (C:'↓'; S:'↓'; K:VK_DOWN; W:60), (C:'→'; S:'→'; K:VK_RIGHT; W:60), (C:'Home'; S:'Home'; K:VK_HOME; W:60), (C:'End'; S:'End'; K:VK_END; W:60), (C:'Up'; S:'Up'; K:VK_PRIOR; W:60), (C:'Dn'; S:'Dn'; K:VK_NEXT; W:60), (C:''; S:''; K:0; W:0), (C:''; S:''; K:0; W:0), (C:''; S:''; K:0; W:0), (C:''; S:''; K:0; W:0) ) ); Const IMC_GETOPENSTATUS=$5; IMC_SETOPENSTATUS=$6; implementation {$R *.dfm} uses Winapi.Imm; { TForm1 } procedure TForm1.SetKeyBoard; var x,y:Integer; CapsLockState:SmallInt; begin // CAPS LOCKの状態を取得 CapsLockState := (GetKeyState(VK_CAPITAL) AND 1); for y := Low(kbd) to High(kbd) do begin for x := Low(kbd[y]) to High(kbd[y]) do begin if kbd[y][x].C='Shift' then begin if IsShift then kbd[y][x].SB.Font.Color:=clRed else kbd[y][x].SB.Font.Color:=clBlack; end else if kbd[y][x].C='Cap' then begin if CapsLockState=1 then kbd[y][x].SB.Font.Color:=clRed else kbd[y][x].SB.Font.Color:=clBlack; end; if IsShift then begin if (CapsLockState=1) and (Length(kbd[y][x].S)=1) then kbd[y][x].SB.Caption:=LowerCase(kbd[y][x].S) else kbd[y][x].SB.Caption:=kbd[y][x].S; end else begin if (CapsLockState=1) and (Length(kbd[y][x].S)=1) then kbd[y][x].SB.Caption:=UpperCase(kbd[y][x].C) else kbd[y][x].SB.Caption:=kbd[y][x].C; end; end; end; end; procedure TForm1.CreateParams(var Params: TCreateParams); begin inherited; Params.ExStyle := (Params.ExStyle or WS_EX_NOACTIVATE //アクティブにならないウィンドウ or WS_EX_TOPMOST //常に手前に配置 ) // and (not WS_EX_APPWINDOW) //タスクバーに配置しない ; end; procedure TForm1.FormCreate(Sender: TObject); var x,y,w:Integer; sb:TSpeedButton; begin Self.ClientWidth := 60*15; Self.ClientHeight := 60*6; IsShift:=False; for y := Low(kbd) to High(kbd) do begin w:=0; for x := Low(kbd[y]) to High(kbd[y]) do begin if kbd[y][x].C<>'' then begin sb:=TSpeedButton.Create(Self); sb.Parent:=Self; sb.Width:=kbd[y][x].W; if kbd[y][x].C='Ent' then sb.Height:=120 else sb.Height:=60; sb.Font.Height:=-16; sb.Left:=w; sb.Top:=y*60; sb.Tag:=x+(y shl 8); sb.OnClick:=BtnClick; kbd[y][x].SB:=sb; inc(w, kbd[y][x].W); end; end; end; SetKeyBoard(); end; procedure TForm1.BtnClick(Sender: TObject); var sb:TSpeedButton; h,hIME:HWND; meStatus:NativeInt; Key:Byte; ScanCode:Cardinal; x,y:Byte; begin sb:=TSpeedButton(Sender); y:=(sb.Tag shr 8); x:=(sb.Tag and $FF); if kbd[y][x].K=255 then begin //フォアグラウンドウィンドウを取得 h:=GetForegroundWindow(); //IMEクラスの既定のウィンドウハンドルを取得 hIME:=ImmGetDefaultIMEWnd(h); if hIME<>0 then begin meStatus := SendMessage(hIME, WM_IME_CONTROL, IMC_GETOPENSTATUS, 0); if meStatus=1 then SendMessage(hIME, WM_IME_CONTROL, IMC_SETOPENSTATUS, 0) else SendMessage(hIME, WM_IME_CONTROL, IMC_SETOPENSTATUS, 1); end; end else if kbd[y][x].K=VK_SHIFT then begin IsShift:=not IsShift; SetKeyBoard(); end else begin if IsShift then begin ScanCode:=MapVirtualKey(VK_SHIFT, MAPVK_VK_TO_VSC); keybd_event(VK_SHIFT,ScanCode,0,0); end; Key:=kbd[y][x].K; ScanCode:=MapVirtualKey(Key, MAPVK_VK_TO_VSC); keybd_event(Key,ScanCode,0,0); keybd_event(Key,ScanCode,KEYEVENTF_KEYUP,0); if IsShift then begin ScanCode:=MapVirtualKey(VK_SHIFT, MAPVK_VK_TO_VSC); keybd_event(VK_SHIFT,ScanCode,KEYEVENTF_KEYUP,0); end; if Key=VK_CAPITAL then SetKeyBoard(); end; end; end.
イベントプロパティの設定
キーボードから「F12」キーを押してデザインエディタに切り替えます。
左上ペイン「構造」から「Form1」をクリックします。
左下ペイン「オブジェクト インスペクタ」から「イベント」タブをクリックし「OnCreate」イベントプロパティに「FormCreate」を設定します。
プロジェクト オプションの設定
「プロジェクト」⇒「オプション」をクリックします。
左上ペイン「アプリケーション」⇒「マニフェスト」を選択します。
「DPIの認識」の設定を「なし」に設定し「保存」ボタンをクリックします。
「実行」⇒「実行」をクリックすると、コンパイルして実行されます。