2025-11-21 全部集約したものになりました。 torazaemon2016.hatenablog.jp
以下は、上ができる前までの内容です。
AutohotkeyのGUIを使って、物理的なキーボードのないPC (Surface)を、ペンや指だけで操作するを目指すシリーズで、実用的なタッチタイプキーボードの実装に、「けいならべ」のような配置を追加したものです。
この前の記事 torazaemon2016.hatenablog.jp
Keyword: Autohotkey, ahk, タッチタイプキーボード, スクリーンキーボード, 仮想キーボード, Virtual keyboard, けいならべ
なお、Autohotkeyの詳しいことやインストールなどについては、他の詳しいページを参考にしてください。
40%キーボード+けいならべ もどきスクリーンタッチキーボード
自分でキー配置を自由に配置できる、分離QWERTYスクリーンタッチキーボードです。
いわゆる40%キーボードとかと呼ばれている、キーの数が少ないキーボードを参考にして、画面が狭くならないスクリーンキーボードを目指したものです。
通常のQWERTY配列のものを、左Shiftキー、右Shiftキー、Numberキー、Funcキーという切り替えキーで、キーの種類を切り替えます。
これに、日本語IMEのON/offキーをわかりやすく、スペースキーの左右に配置して、状態も表示しています。

「A->あ」ボタンを押して、日本語IMEをONにした

サイズを小さいものに

左Shiftキー(大文字)

Number(数字中心配置)

Func(機能中心)

今回は、QWERTY配列だけではなく、ローマ字日本語入力として「けいならべ」を参考にした配列を追加しています。
けいならべもどき配置

「けいならべ」とは左手側に子音、右手側に母音がある並びです。
分離ではなく普通の一体型40%QWERTYも作りましたので追加しておきます(2025/10/13)
分離QWERTY+けいならべもどき配置
Autohotkeyでのプログラムです
; 2025-10-05 分離QWERTY+けいならべもどき by torazemon2016
; 参考
; title: "Can buttons in GUI act like keyboard keys?"
; https://www.reddit.com/r/AutoHotkey/comments/13gawje/can_buttons_in_gui_act_like_keyboard_keys/
#Requires AutoHotkey 2.0+ ; Version 2以上
;IME_SET,GET() IME制御ライブラリを使用
; https://qiita.com/kenichiro_ayaki/items/d55005df2787da725c6f
#Include "IMEv2.ahk"
; --- キーボードボタンのCSVデータ ---
; ( ... ) は 行継続 (continuation section)
; AutoHotkey では、( で始めて ) で終わる部分を「行継続セクション」でこの中はそのまま文字列リテラルとして扱われる
; csv := と 次の行の ( と 次の行の " は、このとおりにしておかないとエラー。同様に、一番最後の " と ) も独立行
csv :=
(
"
; 記述の ;から書き始まっているのは読み飛ばす
; 1:button名, 2:normal, 3:左shift, 4:右シフト, 5:Number, 6:Func, 7:けいならべ, (8:コメント) の必須7項目と、任意のコメントの8項目の並び
; 2025-09-23 分離QWERTY
; qwerty 1段 40%キーボードでは使用せず
bnEsc,Esc,Esc,Esc,Esc,SIZE,,, comment test Escape key size変更
bn1,1,~,!,!,F1,F1,,
bn2,2,`",\,`",F2,F2,, ; ダブルコーテーションは`でエスケープすることでエラーを回避
bn3,3,#,#,F3,F3,,
bn4,4,$,$,F4,F4,,
bn5,5,%,%,F5,F5,,
bn6,6,&&,&&,F6,F6,, ;Buttonコントロールに&文字を表示させるには、&&と記述する。send_key関数でも case '&&' としてやる必要がある
bn7,7,',',F7,F7,,
bn8,8,(,(,F8,F8,,
bn9,9,),),F9,F9,,
bn0,0,|,|,F10,F10,, ; | を 0のshiftにする
bnHat,^,~,~,~,End,, ;分離では未使用
bnEnmark,\,\,|,|,|,, ;分離では未使用 円マークと|のキーはキー削除のため | を 0のshiftにする
bnBackspace,BS,BS,}+{BS,BS,BS,BS,
; qwerty 2段
bnTab,Tab,Tab,}+{Tab,Esc,HIDE,Esc, HIDEは両windowを隠す
bnq,q,Q,!,1,F1,f, ; q->f
bnw,w,W,`",2,F2,w, ;ダブルコーテーションは`でエスケープすることでエラーを回避
bne,e,E,#,3,F3,m,
bnr,r,R,$,4,F4,r,
bnt,t,T,%,5,F5,p,
bny,y,Y,&&,6,F6,}ye{, ; &&にしなければならないことに注意
bnu,u,U,',7,F7,}yo{, ; 'は特別な処理せずともいける
bni,i,I,(,8,F8,u,
bno,o,O,),9,F9,o,
bnp,p,P,|,0,F10,x,
bnAtmark,@,A.``,[,{,,, ;分離では未使用 backquoteは`でエスケープすることで`の1文字になる
bnLBracket,[,[,{,{,{,, ;分離では未使用
; qwerty 3段 CaspはLCtrl
bnLCtrl,LCtrl,LCtrl,LCtrl,LCtrl,LCtrl,LCtrl,
bna,a,A,+,+,}^a{,n,
bns,s,S,-,-,}^s{,s,
bnd,d,D,*,*,}^d{,t,
bnf,f,F,/,/,}^f{,k,
bng,g,G,=,=,}^g{,h,
bnh,h,H,;,;,}^a{,}yu{,
bnj,j,J,:,:,}^s{,a,
bnk,k,K,[,[,,i,
bnl,l,L,],],Home,e,
bnSemiColon,;,,+,PgDn,,, ;分離では未使用
bnColon,:,,*,],,, ;分離では未使用
bnRBracket,],,},},},, ;分離では未使用
bnMinus,-,=,@,``,End,-, ; 1段から3段へ backquoteは`でエスケープすることで`の1文字になる
bnEnter,Enter,Enter,}+{Enter,Enter,Enter,Enter,Enter,
; qwerty 4段
bnLShift,LShift,LLL,LShift,LShift,LShift,LShift,
bnz,z,Z,~,$,}^z{,v, ;けいならべでは、vaのヴぁは出せないのでv
bnx,x,X,^,%,}^x{,z,
bnc,c,C,\,\,}^c{,d,
bnv,v,V,|,<,}^v{,g,
bnb,b,B,_,>,}^b{,b,
bnn,n,N,!,!,}^z{,}ya{,
bnm,m,M,?,?,}^x{,}nn{,
bnComma,,,,,,,, ;コンマはCSVで文字として扱うのは面倒なのでMakeMapsFromCSV関数で直接代入することで処理する
bnPeriod,.,>,},.,}^v{,.,
bnSlash,/,/,?,?,?,, ;分離では未使用
bnUnder,\,_,PgUp,,,, ;分離では未使用
bnUp,Up,Up,}+{Up,Up,}+{Up,Up,
bnRShift,RShift,RShift,RRR,RShift,RShift,RShift, ;RShift は領域選択ができる(+をつけて送出する処理)
; 5段目
bnNumber,Number,Number,Number,NNN,Number,Number, ; 記号キー(数字キー)(実キーボードにはない創作キー) send_key()関数で処理
bnLWin,LWin,LWin,LWin,LWin,LWin,LWin,
bnLAlt,LAlt,LAlt,LAlt,LAlt,LAlt,LAlt,
bnvk1D,無変換,無変換,無変換,無変換,無変換,無変換, ;無変換キー vk1D
bnSpace,Space,Space,Space,Space,Space,Space, ;左スペースキー すべてノーマル
bnRSpace,Space,Space,}+{Space, ,SIZE,Enter, ;右スペースキー Number時全角空白、Funcのときサイズ変更に
bnvk1C,変換,変換,変換,変換,変換,変換, ;変換キー vk1C
bnFunc,Func,Func,Func,Func,FFF,Func, ;特殊キー(実キーボードにはない創作キー) send_key()関数で処理
bnLeft,Left,Left,}+{Left,Left,}+{Left,Left,
bnDown,Down,Down,}+{Down,Down,}+{Down,Down,
bnRight,Right,Right,}+{Right,Right,}+{Right,Right,
; 物理キーには定義がある特殊キー---------------
bnRWin,RWin,RWin,RWin,RWin,RWin,RWin, ;分離では未使用
bnRCtrl,RCtrl,RCtrl,RCtrl,RCtrl,RCtrl,RCtrl, ;分離では未使用
bnRAlt,RAlt,RAlt,RAlt,RAlt,RAlt,RAlt, ;分離では未使用
bnF11,F11,F11,F11,F11,F11,F11, ;分離では未使用
bnF12,F12,F12,F12,F12,F12,F12, ;分離では未使用
bnF13,F13,F13,F13,F13,F13,F13, ;分離では未使用
bnF14,F14,F14,F14,F14,F14,F14, ;分離では未使用
bnF15,F15,F15,F15,F15,F15,F15, ;分離では未使用
bnF16,F16,F16,F16,F16,F16,F16, ;分離では未使用
"
)
; ) で 継続行終わり
; --- CSVからMap化する関数 ---
MakeMapsFromCSV(csvText) {
;bm1 := Map() ; reverse map (normal を button name にマップ (asc2bn))不要に
bm2 := Map() ; 英字表示マップ (normal)
bm3 := Map() ; LShift表示マップ(LShift)
bm4 := Map() ; RShift表示マップ(RShift)
bm5 := Map() ; Number表示マップ(Number)
bm6 := Map() ; Func表示マップ (Func)
bm7 := Map() ; けいならべ表示マップ(Keinarabe)
Loop Parse, csvText, "`n", "`r"
{
line := Trim(A_LoopField)
if ( (line = "") || (InStr(line, ";", 0, 1) = 1) ) ; 読み飛ばし定義: 空行 または 1文字目が「;」
continue
;MsgBox("line=" line)
parts := StrSplit(line, ",") ; , で分ける
if (parts.Length >= 6) { ; 7項目以上
Try {
btnname := parts[1]
normal := parts[2]
LShift := parts[3]
RShift := parts[4]
Number := parts[5]
Func := parts[6]
Keinarabe := parts[7] ; けいならべ
comment := parts[8] ; 読み捨てるだけだけど、7項目(,が6つ)がなければエラーでcatchへ
;bm1[normal] := btnname ; 不要に
bm2[btnname] := normal
bm3[btnname] := LShift
bm4[btnname] := RShift
bm5[btnname] := Number
bm6[btnname] := Func
bm7[btnname] := Keinarabe
} Catch as e {
MsgBox("error: " btnname) ; 定義ミスボタン名を表示 (,の間違いなどのミス)
exit ; 終了する
}
}
}
; 文字Comma「,」 は特別扱い csvロード関数(MakeMapsFromCSV)でやるには例外処理面倒いので、以下のように直接代入する
;bm1[","] := "bnComma" ; 不要に
bm2["bnComma"] := "," ; normal
bm3["bnComma"] := "<" ; LShift
bm4["bnComma"] := "{" ; RShift
bm5["bnComma"] := "," ; Number
bm6["bnComma"] := "}^c{" ; Func
bm7["bnComma"] := "," ; Keinarabe
;return [bm1, bm2, bm3, bm4, bm5, bm6] ; 配列で返す
return [bm2, bm3, bm4, bm5, bm6, bm7] ; 配列で返す
}
; --- CSVからMap作成 ---
maps := MakeMapsFromCSV(csv)
bn2asc_map := maps[1]
bn2LShift_map := maps[2]
bn2RShift_map := maps[3]
bn2Number_map := maps[4]
bn2Func_map := maps[5]
bn2Kei_map := maps[6]
; --- キーラベル(ボタン名bn???)から文字を取得関数 ---
; モード切替用大域変数
global CurrentMode := "normal" ; 初期値: normal(ノーマルキー) LShift(シフトキー) RShift(右シフト) Number(記号) Func(F1など拡張) Keinarabe(けいならべ)
GetKey2Name(key) {
global CurrentMode, bn2asc_map, bn2LShift_map, bn2RShift_map, bn2Number_map, bn2Func_map, bn2Kei_map
;MsgBox(key)
if (CurrentMode = "normal")
return bn2asc_map.Has(key) ? bn2asc_map[key] : ""
else if (CurrentMode = "LShift")
return bn2LShift_map.Has(key) ? bn2LShift_map[key] : "" ; lshift
else if (CurrentMode = "RShift")
return bn2RShift_map.Has(key) ? bn2RShift_map[key] : ""
else if (CurrentMode = "Number")
return bn2Number_map.Has(key) ? bn2Number_map[key] : ""
else if (CurrentMode = "Func")
return bn2Func_map.Has(key) ? bn2Func_map[key] : ""
else
return bn2Kei_map.Has(key) ? bn2Kei_map[key] : ""
}
/**************************************************************************/
; キーボードの並びの配列
; QWERTY
/*
key_table := [
[ 'bnEsc', 'bn1', 'bn2', 'bn3', 'bn4', 'bn5', 'bn6', 'bn7', 'bn8', 'bn9', 'bn0','bnMinus', 'bnHat', 'bnBackspace' ]
,[ 'bnTab', 'bnq', 'bnw', 'bne', 'bnr', 'bnt', 'bny', 'bnu', 'bni', 'bno', 'bnp','bnAtmark', 'bnLBracket' , 'bnEnter' ]
,[ 'bnLCtrl', 'bna', 'bns', 'bnd', 'bnf', 'bng', 'bnh', 'bnj', 'bnk', 'bnl', 'bnSemiColon', 'bnColon', 'bnRBracket' ]
,[ 'bnLShift', 'bnz', 'bnx', 'bnc', 'bnv', 'bnb', 'bnn', 'bnm', 'bnComma', 'bnPeriod', 'bnSlash', 'bnUnder', 'bnUp', 'bnRShift' ]
,[ 'bnFunc', 'bnLWin', 'bnLAlt', 'bnvk1D', 'bnSpace', 'bnvk1C', 'bnF14', 'bnF15', 'bnRAlt', 'bnLeft', 'bnDown', 'bnRight' ]
]
*/
; 分離QWERTY
key_table_left := [
[ 'bnTab', 'bnq', 'bnw', 'bne', 'bnr', 'bnt']
,[ 'bnLCtrl', 'bna', 'bns', 'bnd', 'bnf', 'bng']
,[ 'bnLShift', 'bnz', 'bnx', 'bnc', 'bnv', 'bnb']
,[ 'bnNumber', 'bnLWin', 'bnLAlt', 'bnvk1D', 'bnSpace' ]
]
key_table_right := [
[ 'bny', 'bnu', 'bni', 'bno', 'bnp', 'bnBackspace']
,[ 'bnh', 'bnj', 'bnk', 'bnl', 'bnMinus', 'bnEnter' ]
,[ 'bnn', 'bnm', 'bnComma', 'bnPeriod', 'bnUp', 'bnRShift']
,[ 'bnRSpace', 'bnvk1C', 'bnFunc', 'bnLeft', 'bnDown', 'bnRight']
]
/********************************************************/
; キーボード起動 (Autohotkey起動時に直接起動。Hotkey()で起動Keyを定義)
virtual_keyboard_katanakai(2) ; 1:small 2:large サイズで起動
/********************************************************/
; ここからが本体
virtual_keyboard_katanakai(size,*)
{
/******************/
; 以下は同時にON (押されているがあるので、(Shiftの)Global CurrentModeとは違う扱い)
AltState := 0 ; ALtキーが押されてるか1 ない 0
CtrlState := 0 ; Ctrlキーが押されてるか1 ない 0
WinState := 0 ; Winキーが押されてるか1 ない 0
keysize := size ; keyboardの大きさ (SIZEキー) ; 1: small size, 2: large size
/******************/
;左キーボードGUIオブジェクトを作成
;guikeyboard := Gui('+AlwaysOnTop', "AHK Keyboard") ; これだと文字がエディタなどに入力されない
gui1 := Gui('+AlwaysOnTop +E0x08000000', "AHK Keyboard") ; これだと文字を送れる ; "WS_DISABLED"
key_table := key_table_left
make_keyboard(gui1,key_table,size)
gui1.Show('x0 y1000 NoActivate') ; 画面左上
;右キーボードGUIオブジェクトを作成
gui2 := Gui('+AlwaysOnTop +E0x08000000', "AHK Keyboard 2") ; これだと文字を送れる ; "WS_DISABLED"
key_table := key_table_right
make_keyboard(gui2,key_table,size) ; 1: small size, 2: large size
gui2.Show('x1600 y1000 NoActivate') ; 画面右上
; Hotキーの定義
toggle_hotkey := 'F5' ; Hotkey
Hotkey("*" toggle_hotkey, CloseWindows) ; keyboard on/off
gui1.OnEvent("Close", CloseWindows1) ; X で閉じるとき
gui2.OnEvent("Close", CloseWindows2) ; X で閉じるとき
OnExit(clear_mods) ; 終了時 実行するもの
/***** 内部関数 **********************************************/
; 両方のWindowを同時に閉じる(Hideする)-----
CloseWindows(*)
{
clear_mods() ; 万が一、装飾キーがONになっているのをクリアするため
if WinExist('ahk_id ' gui1.hwnd)
{
gui1.Hide()
}
else
{
gui1.Show('NoActivate')
}
if WinExist('ahk_id ' gui2.hwnd)
{
gui2.Hide()
}
else
{
gui2.Show('NoActivate')
}
}
; 1のWindowを閉じる(Hideする)-----
CloseWindows1(*)
{
clear_mods() ; 万が一、装飾キーがONになっているのをクリアするため
if WinExist('ahk_id ' gui1.hwnd)
gui1.Hide()
;else
;gui1.Show('NoActivate')
}
; 2のWindowを閉じる(Hideする)-----
CloseWindows2(*)
{
clear_mods() ; 万が一、装飾キーがONになっているのをクリアするため
if WinExist('ahk_id ' gui2.hwnd)
gui2.Hide()
;else
;gui2.Show('NoActivate')
}
; 万が一、Ctrlキーなどが押されたままになっていたりするのを、それを外すため
clear_mods(*) {
for _, key in ['lshift', 'rshift', 'lctrl', 'rctrl', 'lalt', 'ralt', 'lwin', 'rwin']
if GetKeyState(key) ; もし押されたままの状態だったら
SendInput('{' key ' Up}') ; 上げる(押されてない)にする
}
;keyboard作成------------------
make_keyboard(guio,key_table,size,*)
{
; サイズ指定
;MsgBox("size = " size) ;
if(size == 1)
{
; 小さいタイプ
margin := 0 ; キーとキーの間
btn_w := 60 ; 70
btn_h := 50 ; 70
guio.SetFont("s14") ; フォントサイズ(ポイント)
}
else
{
; 大きめ
margin := 1 ; キーとキーの間
btn_w := 90 ; ボタンの幅
btn_h := 90 ; ボタンの高さ
guio.SetFont("s18") ; フォントサイズ(ポイント)を設定
}
guio.MarginX := guio.MarginY := margin
guio.BackColor := "Silver" ; 背景色
for _, row in key_table { ; 段毎
y := margin + (A_Index-1) * (margin + btn_h) ; 各段のY座標
for _, bnkey in row { ; 段での各文字毎
w := 0
h := 0
offset := 0 ; 右の最初やEnterキーのずれの位置合わせのため
switch bnkey
{
case 'bnEsc': ; 1段目左端
w := btn_w * 0.8 ; 少し小さく
h := btn_h
case 'bnTab': ; 2段目左端
w := btn_w * 1.0
h := btn_h
case 'bnLCtrl': ; 3段目左端
w := btn_w * 1.2
h := btn_h
case 'bnLShift': ; 4段目左端
w := btn_w * 1.4
h := btn_h
case 'bnF13': ; 5段目左端
w := btn_w * 1
h := btn_h
case 'bnSpace': ; スペースキー
w := btn_w * 1.4 + btn_w * 1 + margin * 1 ; LShiftの幅分 + 1キー分 + 1つ分の隙間
h := btn_h
case 'bn6': ; 分離右 1段目左
w := btn_w * 1
h := btn_h
offset := 0
case 'bnBackspace': ; 分離1段目右端
;w := btn_w * 0.6 + btn_w * 1
w := btn_w * 0.4 + btn_w * 1
h := btn_h
case 'bny': ; 分離右 2段目左
w := btn_w * 1
h := btn_h
;offset := btn_w * 0.2
case 'bnEnter': ; Enterキー
;w := btn_w * 1.2 ; Enterの幅
;h := btn_h * 2.0 + margin ; Enterの高さ ; 2段分+1つ分の隙間
;w := btn_w * 2.2 + margin ; Enterの幅 2個分+marginの分
w := btn_w * 1.2 margin ; Enterの幅 2個分+marginの分
h := btn_h ; Enterの高さ ; 1段分
;offset := btn_w * 0.2 ; p と Enterとの間 3段目に横長になった
case 'bnh': ; 分離右 3段目左
w := btn_w * 1
h := btn_h
;offset := btn_w * 0.4
offset := btn_w * 0.2
case 'bnn': ; 分離右 4段目左
w := btn_w * 1
h := btn_h
;offset := btn_w * 0.6
offset := btn_w * 0.4
case 'bnRSpace': ; 分離右 5段目 右スペースキー
;w := btn_w * 0.6 + btn_w * 2 + margin * 1 ; bnnずれ幅分 + 2キー分 + 1つ分の隙間
;w := btn_w * 0.6 + btn_w * 1 ; bnnずれ幅分 + 1キー分 (RCtrlありのとき)
w := btn_w * 0.4 + btn_w * 1 ; bnnずれ幅分 + 1キー分 (RCtrlありのとき)
h := btn_h
offset := 0
default:
w := btn_w ; 普通のキーwidth
h := btn_h ; 普通のキーheight
}
if (A_Index = 1) ; 各段の最初のキー
con := guio.AddButton('xm+' offset ' y' y ' w' w ' h' h ' v' bnkey, GetKey2Name(bnkey))
else ; 最初以外のキー
con := guio.AddButton('x+' margin + offset ' yp ' ' w' w ' h' h ' v' bnkey, GetKey2Name(bnkey))
con.OnEvent('Click', send_key.Bind(bnkey)) ; bn??? ボタンの名前(bn???で登録)
}
}
}
; 表示を切り替える----------
change_keyboard(*)
{
global CurrentState
for _, btn in gui1 {
;MsgBox("btn.Text = " btn.Text) ;
btn.Text := GetKey2Name(btn.Name)
}
for _, btn in gui2 {
;MsgBox("btn.Text = " btn.Text) ;
btn.Text := GetKey2Name(btn.Name)
}
; Toggle IME
if(IME_GET() == 1)
{
gui1["bnvk1D"].Text := "あ->A"
gui2["bnvk1C"].Text := "あ"
}
else
{
gui1["bnvk1D"].Text := "A"
gui2["bnvk1C"].Text := "A->あ"
}
if(CurrentMode == "Func")
{
gui2["bnvk1C"].Text := "けいならべ"
}
if(CtrlState == 1)
{
gui1["bnLCtrl"].Text := "CCC"
;gui2["bnRCtrl"].Text := "CCC" ; 今回未使用
}
if(AltState == 1)
{
gui1["bnLAlt"].Text := "AAA"
;gui2["bnRAlt"].Text := "AAA" ; 今回未使用
}
if(WinState == 1)
{
gui1["bnLWin"].Text := "WWW"
;gui2["bnRWin"].Text := "WWW" ; 今回未使用
}
set_BackgroundColor()
}
; 背景色をセットする
set_BackgroundColor(*) ;
{
global CurrentMode
;MsgBox("Ctrl " CtrlState " Alt " AltState " Win " WinState)
; 上から優先
if(CtrlState == 1)
{
gui1.BackColor := "Yellow"
gui2.BackColor := "Yellow"
}
else if(AltState == 1)
{
gui1.BackColor := "Olive"
gui2.BackColor := "Olive"
}
else if(WinState == 1)
{
gui1.BackColor := "Blue"
gui2.BackColor := "Blue"
}
else if(CurrentMode == "Func")
{
gui1.BackColor := "Maroon"
gui2.BackColor := "Maroon"
}
else if(CurrentMode == "Number")
{
gui1.BackColor := "Lime"
gui2.BackColor := "Lime"
}
else if(CurrentMode == "LShift")
{
gui1.BackColor := "Fuchsia"
gui2.BackColor := "Fuchsia"
}
else if(CurrentMode == "RShift")
{
gui1.BackColor := "Red"
gui2.BackColor := "Red"
}
else if(IME_GET() == 1) ; IME ON
{
;MsgBox("IME_GET()" IME_GET())
gui1.BackColor := "Green"
gui2.BackColor := "Green"
}
else
{
;MsgBox("IME_GET()" IME_GET())
gui1.BackColor := "Silver"
gui2.BackColor := "Silver"
}
}
; キー送出---------
modifykey := "" ; 複数入力を覚えておく必要があるので関数の外に変数
; ^!# が入る (また+のshiftはまた別 選択とかモードとかで扱いを別にしている)
send_key(key2,*)
{
global CurrentMode
key := Getkey2Name(key2) ;bn???->文字
;MsgBox("send_key =" key2 " GetKey2Name=" key)
switch key {
case '&&': ; &はautootkeyでのbutton表示で特別扱いが必要なため
;MsgBox("case && send_key =" key2 " GetKey2Name=" key)
key := "&"
SendInput('{Blind}{' key '}')
case 'SIZE': ;
;MsgBox("case && send_key =" key2 " GetKey2Name=" key)
if WinExist('ahk_id ' gui1.hwnd)
gui1.Destroy()
if WinExist('ahk_id ' gui2.hwnd)
gui2.Destroy()
if(keysize == 1) ; 1: small size, 2: large size
{
virtual_keyboard_katanakai(2) ; 2:largeサイズで起動
}
else
{
virtual_keyboard_katanakai(1) ; 1:smallサイズで起動
}
case 'HIDE':
;MsgBox("case && send_key =" key2 " GetKey2Name=" key)
CurrentMode := "normal" ; 次に表示するときにはnormal表示に (そのままだとFuncのまま)
change_keyboard()
CloseWindows()
case '変換': ; vk1C
if(CurrentMode == "Keinarabe") ; けいならべ
{
return
}
;MsgBox("case && send_key =" key2 " GetKey2Name=" key)
IME_SET(1) ; IMEをON
sleep(100) ; PC性能によりスピード調整が必要かも
if(IME_GET() == 1)
{
if(CurrentMode == "Func")
{
CurrentMode := "Keinarabe" ; けいならべ
}
else
{
CurrentMode := "normal"
}
change_keyboard()
}
else
{
; もう一度チャレンジ
IME_SET(1) ; IMEをON
sleep(100) ; PC性能によりスピード調整が必要かも
if(IME_GET() == 1)
{
if(CurrentMode == "Func")
{
CurrentMode := "Keinarabe" ; けいならべ
}
else
{
CurrentMode := "normal"
}
change_keyboard()
}
else
{
MsgBox("IME_ONに変わりませんでした 右下のIMEの状態を確認して再度押してみてください")
}
}
case '無変換': ; vk1D
;MsgBox("case && send_key =" key2 " GetKey2Name=" key)
IME_SET(0) ; IMEをoff
sleep(100)
if(IME_GET() == 1)
{
MsgBox("IME_offに切り替わりませんでした 申し訳ありませんが再度押してみてください")
}
else
{
CurrentMode := "normal"
change_keyboard()
}
/***装飾キー 押したかどうかのところ****************/
case 'Alt': goto ALT
case 'LAlt': goto ALT
case 'RAlt':
ALT:
AltState := (AltState = 0) ? 1 : 0
;MsgBox("Alt =" AltState)
change_keyboard() ; 色も関数でやる
case 'Ctrl': goto CTRL
case 'LCtrl': goto CTRL
case 'RCtrl':
CTRL:
CtrlState := (CtrlState = 0) ? 1 : 0
;MsgBox("Ctrl =" CtrlState)
change_keyboard() ; 色も関数でやる
case 'LWin': goto wIN
case 'RWin':
WIN:
if(WinState == 1) ; Win のあと再度Winを押すと Winキーを押したのと同じにしてスタートメニューを開く
{
SendInput('{Blind}' modifykey '{' key '}')
}
WinState := (WinState = 0) ? 1 : 0
;MsgBox(""in =" WinState)
change_keyboard() ; 色も関数でやる
/***Mode(状態)のところ****************/
case 'LLL': goto LSFT
case 'Shift': goto LSFT
case 'LShift':
LSFT:
gui2.Show('NoActivate')
if((AltState == 1) || (CtrlState == 1 ) || (WinState == 1)) ; 修飾キーONのときはモード変えない
goto END
CurrentMode := (CurrentMode != "LShift") ? "LShift" : "normal"
;MsgBox("Lshift =" CurrentMode " Key=" key " key2=" key2)
change_keyboard() ; 色も関数でやる
case 'RRR': goto RSFT
case 'RShift':
RSFT:
gui1.Show('NoActivate')
if((AltState == 1) || (CtrlState == 1 ) || (WinState == 1)) ; 修飾キーONのときはモード変えない
goto END
CurrentMode := (CurrentMode != "RShift") ? "RShift" : "normal"
;MsgBox("Rshift =" CurrentMode " Key=" key " key2=" key2)
change_keyboard() ; 色も関数でやる
case 'FFF': goto FUNC
case 'Func':
FUNC:
if((AltState == 1) || (CtrlState == 1 ) || (WinState == 1)) ; 修飾キーONのときはモード変えない
goto END
CurrentMode := (CurrentMode != "Func") ? "Func" : "normal"
;MsgBox("Func =" CurrentMode " Key=" key " key2=" key2)
change_keyboard()
case 'NNN': goto NUMBER
case 'Number':
NUMBER:
if((AltState == 1) || (CtrlState == 1 ) || (WinState == 1)) ; 修飾キーONのときはモード変えない
goto END
CurrentMode := (CurrentMode != "Number") ? "Number" : "normal"
;MsgBox("Number =" CurrentMode " Key=" key " key2=" key2)
change_keyboard()
/***実際に文字出力*****************************/
default: ; cvbb
if(CtrlState == 1)
{
modifykey := modifykey . "^"
CtrlState := 0
change_keyboard() ; 色も関数でやる
}
if(AltState == 1)
{
modifykey := modifykey . "!"
AltState := 0
change_keyboard() ; 色も関数でやる
}
if(WinState == 1)
{
modifykey := modifykey . "#"
WinState := 0
change_keyboard() ; 色も関数でやる
}
; 実際に文字出力 '{' と '}' で挟んで出すので、Enterとかそのまま書ける
; F13での }^x とかの } は これの最初の '{' を打ち消すだめ (正確には }^x{ となるけど動いている)
;MsgBox("SendInput(" modifykey "{" key "}")
SendInput('{Blind}' modifykey '{' key '}')
END:
modifykey := "" ;
}
}
}
/* END */
プログラムの簡単な説明(前回から変わったところなど)
前回の記事から、無駄な部分などをかなり整理しました。
最初の部分でのキーボタンの定義のcsv形式は、前回使っていなかった第2項目が消えて、また、ExtraだったものをNumberとかFuncと機能と一致するような名前にし、さらに今回の「けいならべ」配列を追加しています。
; --- キーボードボタンのCSVデータ ---
csv :=
(
"
; 記述の ;から書き始まっているのは読み飛ばす
; 1:button名, 2:normal, 3:左shift, 4:右シフト, 5:Number, 6:Func, 7:けいならべ, (8:コメント) の必須7項目と、任意のコメントの8項目の並び
bnTab,Tab,Tab,}+{Tab,Esc,HIDE,Esc, HIDEは両windowを隠す
bnq,q,Q,!,1,F1,f, ; q->f
bnw,w,W,`",2,F2,w, ;ダブルコーテーションは`でエスケープすることでエラーを回避
bne,e,E,#,3,F3,m,
bnr,r,R,$,4,F4,r,
bnt,t,T,%,5,F5,p,
Funcキーでの画面などで、AutohotkeyでのModifyキー(Ctrl,Alt,Winを^,!,#)扱いになるようにして、それにAutohotkeyでのキー名を送り込むように{}で囲まれるようになっています。 プログラムの最後に送り出すSendInput()がありますので、それを見てもらえれば「 }^c{ 」とかになっている理由もわかるかと思います。
けいならべと同じ配置にするのも難しくはなく、自分が使いやすいように、キー定義やキー配置も、いろいろと改造して、自分が使いやすいキーボードにしてみてください。
TouchPanelGestures
物理キーボードがないので、TouchPanelGesturesアプリは必須です。
プログラム中でホットキーとして「F5」を指定しています。(前のF2からF5に変更)
ジェスチャーとしては「指3本の→↓」に落ち着いてきました。 Surfaceのキーボードのタッチパッドでの、3本指や4本指の操作とTouchPanelGesturesのものが衝突して、意図しない動きが出ることが多く、 三本指で→↓あたりが混乱少なく、キーボードを出したり、隠したりできます。