G-series Lua API のメモ

first edition: 2013-5-9, update: 2014-7-28

初めに

Logicool® ゲーム ソフトウェア (以下 LGS) に搭載されているスクリプト言語 Lua で使える G-series 独自の関数の一覧と概要です。

残念ながら G-series Lua API V8.45 Overview and Reference の日本語訳ではありません。
ある日に Logicool® Optical Gaming Mouse G300 を購入し、スクリプトに興味が湧いたものの自身の英語力も Lua の知識も 0 だったため、動作を一々確認しながらメモしていった結果生まれたページです。
詰まりは細かい点についての情報は含まれておらず、また検証も G300 でしか行っていません。
多々含まれているであろう誤りを発見された時は、拍手コメントなりで指摘していただけると嬉しいです。

正確な情報については以下、参考に列挙しているマニュアル及びサイト様などをご覧ください。

参考

スクリプトの実行

プロファイルに登録されたスクリプトは、以下の条件で実行されます。

また、スクリプト中で OnEvent() 関数を定義することで、以降 OnEvent が次の条件で発火します。

尚、少なくとも OnEvent() 関数が定義されていないと、attempt to call a nil value というエラー (?) メッセージが出力されるため、プロファイル毎のスクリプトも最初から以下のようになっています。

  1. function OnEvent(event, arg)
  2.  --OutputLogMessage("event = %s, arg = %s\n", event, arg);
  3. end

※ 2 行目はコメントなのでスクリプトの実行には関わりません。コメントはハイフンを 2 回続けた後に書きます。

関数の一覧

索引

EnablePrimaryMouseButtonEvents(enable)

通常、OnEvent() はマウスの左ボタン (※1) の押下・押下の解除では発火しません (※2) が、EnablePrimaryMouseButtonEvents() 関数に 1 または true を与えて実行することで発火するように設定を変更できます。0 または false を与えて実行すると発火しなくなります。

戻り値は nil です。

左ボタンによる発火の可否の設定は、プロファイルの切り替えやスクリプトの読み直しが起きてもリセットされません。EnablePrimaryMouseButtonEvents() 関数で再び設定を変更するか LGS が起動し直されるまで有効です。

※1 ここで述べる左ボタンとは物理的な位置でいう左ボタンです。マウスの機能としての左ボタンではなく、Windows のマウスのプロパティ (main.cpl) の「主と副のボタンを切り替える」にも影響されません。仮に左ボタンに A キーの入力を割り当てていたとしても、EnablePrimaryMouseButtonEvents(true) を実行しなければ OnEvent() 関数は発火しません。

※2 マニュアルの備考に「既定では左ボタンに反応しないのはパフォーマンス上の問題のため」的なことが書いてあります。

Sleep(timeout)

timeout に指定したミリ秒 (1000 = 1 秒) だけ、スクリプトを一時停止します。

戻り値は nil です。

OutputLogMessage(...)

スクリプトエディタ下部のメッセージの出力エリアに、任意のメッセージを出力します。

戻り値は nil です。

  1. OutputLogMessage("test\n"); -- test[改行]
  2. a, b = 3, "10";
  3. OutputLogMessage("G-series Lua API %d-%d-%s\n", 2013, a, b); -- G-series Lua API 2013-3-10[改行]

% から始まる変換指示句についてなど、詳しくは Lua 言語のライブラリ関数様の string.format(format, ...) の説明を参照してください。

尚、日本語は試してみましたが "?" に置換されて出力されてしまいました。

OutputLCDMessage(text[, timeout])

キーボード・左手用キーパッドに備え付けられている液晶に表示されるメッセージを、引数 text の内容に変更します。

timeout にはミリ秒で……何だろう。メッセージの表示が続く時間? を指定するのかもしれません。既定値は 1000 (1 秒) です。

日本語が表示できるのか否かも含めて、私は Logicool のキーボードも左手用キーパッドも持っていないので、詳しくはご自身で試されるかマニュアルを確認してくださいませ。

戻り値は nil です。

OutputDebugMessage(...)

OutputLogMessage() 関数とほぼ同じ様子ですが、出力先の "Windows debugger" とやらに私が触れたことがないので詳しくは分かりません。

戻り値は nil です。

ClearLog()

スクリプトエディタ下部のメッセージの出力エリアのすべての内容を消去します。

戻り値は nil です。

ClearLCD()

キーボード・左手用キーパッドに備え付けられている液晶に表示されるメッセージの消去、だと思います。

戻り値は nil です。

GetRunningTime()

スクリプトが実行されてからの経過時間をミリ秒で返します。
※ OnEvent が発火してからの時間ではありません。

GetMousePosition()

プライマリモニタの画面の幅を 0~65535 の値で表現した時のマウスポインタの位置を、多値 x (横), y (縦) で返します。

仮に 0, 0 が得られたならポインタはプライマリモニタの画面の左上に、65535, 65535 が得られたならプライマリモニタの画面の右下にあることになります。

  1. x, y = GetMousePosition();
  2. OutputLogMessage("x = %d, y = %d\n", x, y); -- x = 10000, y = 5000[改行]

マルチモニタ環境においては -1 以下 65536 以上の値も返されますが、正確なところは分かりません。

試しに 1920×1080 px のモニタを左にプライマリ、右にセカンダリと二つ横並びにして、右下にポインタがある時の座標を拾ってみると、x = 131104, y = 65535 という値が返ってきました。単に 65535 + 65536 の値が返ってくる訳ではないようです (式の関係で僅かにブレが生じるのかな?)

GetMKeyState([family])

モード切替キー (ゲーミング キーボードで言う M キー) によって切り替えられるモードの内、何れが選択されているのかを 1~3 の値で返します。

family に "kb" を指定するとキーボード (G15, G11, G19, etc) に、"lhc" を指定すると左手用キーパッド (G13, etc) に対して機能します。省略時の値は "kb" です。

マニュアルには "kb", "lhc" しか列挙されていませんが、"mouse" (マウス) の指定も機能し、同様にカレント モードの値を得ることができます。

SetMKeyState(mkey[, family])

mkey の値に応じてカレント モードを変更します。mkey には 1~3 の値 (ゲーミング キーボードで言う M1~M3 キーに相当) が指定できます。

戻り値はありません。

family の指定は GetMKeyState() 関数に同じで、"mouse" も指定できます。

注: SetMKeyState 実行後、ごく短時間に GetMKeyState() を実行すると、変更前の M キーの値が返されます。マニュアルでも注記されている挙動ですが、原因が、変更が直ぐに反映されないためなのか、GetMKeyState() 側の問題なのかは分かりません。Sleep を挟むなどで対処できます。

SetBacklightColor(red, green, blue[, family])

ハードウェアの LED の色を、RGB それぞれ 0~255 の範囲で指定して変更します。

family には "kb" (キーボード。G15, G11, G19, etc), "lhc" (左手用キーパッド G13, etc) を指定できます。省略時の値は "kb" です。

尚、マニュアルには "kb", "lhc" しか列挙されていませんが、"mouse" を指定して G300 の LED を変更することもできました。但し、RGB それぞれ 0 (0~127) と 255 (128~255) の 2 階調しか表現できませんでした。

G300 で確認した限りでは、変更はスクリプトによる一時的なものであり、LED の設定画面を開くなどで、プロファイルに登録された色に戻ります。

戻り値は nil です。

  1. SetBacklightColor(255, 0, 0); -- LED の色を赤に変更

SetMouseDPITable({value1[, value2, ...]}[, index])

DPI 感度レベルのテーブルを一時的に変更します。

変更は LGS の再起動、プロファイルの切り替え、ポインタ設定画面を開くなどで取り消されます。

テーブルには最大で 16 のエントリを登録できます。

DPI サイクル機能を割り当てたボタンを押した時に、仮に 300, 800, 1400, 2000 dpi の中をサイクルするようにしたければ、SetMouseDPITable({300, 800, 1400, 2000}); のようにします。

index には、登録した DPI の中から何番目のものをアクティブにするのかを 1~ の値で指定します。省略すると 1 番目 (value1) がアクティブになります。

※デフォルト DPI になる訳ではありません。デフォルト DPI は、元のテーブルのデフォルト DPI の登録箇所に相当するエントリになります。

戻り値は nil です。

SetMouseDPITableIndex(index)

詳しくは SetMouseDPITable() 関数を参照してください。

戻り値は nil です。

DPI テーブルは別に書き換えたくないんだ。単に DPI の選択を変更したいだけなんだ。って時に。

PressKey(scancode[, scancode[, ...]] | keyname[, keyname[, ...]])

任意の走査コードまたは定義名に対応するキーを押下します。

以下の例では Ctrl+C, Ctrl+V を実行しています。

  1. PressKey("lctrl"); -- 左 Ctrl キーの押下
  2. PressAndReleaseKey("c", "v"); -- C, V キーの押下と押下の解除
  3. ReleaseKey("lctrl"); -- 左 Ctrl キーの押下の解除

scancode, keyname については G-series Lua API V8.45 Overview and Reference の 44 ページ目の「Appendix A」を参照してください。

戻り値は nil です。

PressHidKey(hidcode[, hidcode[, ...]])

PressKey() 関数と同様に任意の一つまたは複数のキーを押下します。

キーの指定 (hidcode) には HID デバイス クラスの Usage の中の、キーボードの Usage Page の Usage ID を用います。

Usage ID の一覧については参考に列挙している HID Usage Tables 1.12 の 53 ページ目の「10 Keyboard/Keypad Page (0x07)」を参照してください。

  1. -- 行末に改行を挿み、大文字で "ABC" と入力する例
  2. PressAndReleaseHidKey(0x4d, 0x58); -- End, Enter キーの押下と押下の解除
  3. PressHidKey(0xe1); -- 左 Shift キーの押下
  4. PressAndReleaseHidKey(0x04, 0x05, 0x06); -- a, b, c キーの押下と押下の解除
  5. ReleaseHidKey(0xe1); -- 左 Shift キーの押下の解除

戻り値は nil です。

PressMouseButton(button)

引数 button の値に応じたマウス機能の押下を行います。値は次の通りです。

1
左ボタン
2
中ボタン
3
右ボタン
4
X1 (戻る) ボタン
5
X2 (進む) ボタン

G300 で確認した限りでは、引数の値はマウス機能を指すのであって、マウスの物理的なボタンの位置 (番号) を指すものではありません

オンボードメモリに保存されている設定にもよらず、仮に G4 ボタンに「戻る」以外の機能が割り当てられていたとしても、PressMouseButton(4); ReleaseMouseButton(4); は「戻る」を機能させます。

戻り値は nil です。

ReleaseKey(scancode[, scancode[, ...]] | keyname[, keyname[, ...]])

任意のキーの押下を解除します。

scancode, keyname については G-series Lua API V8.45 Overview and Reference の 44 ページ目の「Appendix A」を参照してください。

戻り値は nil です。

ReleaseHidKey(hidcode[, hidcode[, ...]])

ReleaseKey() 関数と同様に任意の一つまたは複数のキーの押下を解除します。

hidcode については PressHidKey() 関数を参照してください。

戻り値は nil です。

PressAndReleaseKey(scancode[, scancode[, ...]] | keyname[, keyname[, ...]])

任意のキーの押下・押下の解除をまとめて行います。

scancode, keyname については G-series Lua API V8.45 Overview and Reference の 44 ページ目の「Appendix A」を参照してください。

複数のキーを指定した場合、すべてのキーを押下してから順次押下を解除するのではなく、一つずつ押下・押下の解除が行われます。

詰まり、PressAndReleaseKey("a", "b");PressAndReleaseKey("a"); PressAndReleaseKey("b"); と同じです。

戻り値は nil です。

PressAndReleaseHidKey(hidcode[, hidcode[, ...]])

PressAndReleaseKey() 関数と同様に任意の一つまたは複数のキーの押下・押下の解除をまとめて行います。

hidcode については PressHidKey() 関数を参照してください。

戻り値は nil です。

PressAndReleaseMouseButton(button)

任意のマウス機能の押下・押下の解除をまとめて行います。

button、戻り値については PressMouseButton() 関数に同じです。

IsModifierPressed(keyname)

keyname で示した修飾キー (Ctrl, Shift, Alt) が押下されていれば true を、いなければ false を返します。

keyname には次のものを使用できます。

"lctrl"
左 Ctrl キー
"rctrl"
右 Ctrl キー
"ctrl"
Ctrl キー
"lshift"
左 Shift キー
"rshift"
右 Shift キー
"shift"
Shift キー
"lalt"
左 Alt キー
"ralt"
右 Alt キー
"alt"
Alt キー

IsMouseButtonPressed(button)

引数 button の値に応じたマウスの機能が割り当てられているボタンが押下されていれば true を、されていなければ false を返します。

値は PressMouseButton() 関数に同じです。

  1. function OnEvent(e, a)
  2.  OutputLogMessage("Left mouse button: " .. (IsMouseButtonPressed(3) and "on" or "off") .. "\n");
  3. end

注: マニュアルによると、PressMouseButton() 関数などによる操作の完了には数ミリ秒掛かるらしく、短時間に IsMouseButtonPressed() 関数を呼んだ場合、PressMouseButton() 関数に指定した値とは異なる値が返ることがあるそうです。

IsKeyLockOn(key)

key に "scrolllock" を指定すると Scroll Lock、"capslock" で Caps Lock、"numlock" で Num Lock の状態を調べ、on になっていれば true を、いなければ false を返します。

MoveMouseTo(x, y)

マウスポインタを任意の横位置 x, 縦位置 y に移動させます。

位置は解像度に関わらず、プライマリモニタの画面の上端・左端を 0、下端・右端を 65535 とした時の範囲で指定します。

例えば、MoveMouseTo(32767, 32767) は、マウスポインタをプライマリモニタの画面の中央に移動させます。

戻り値は nil です。

尚、複数のモニタを跨る位置を指定することはできません。マルチモニタ環境か否かに関わらず、-1 以下 65536 以上の値を指定したなら、エラーメッセージ "argument out of range" を吐きます。

複数のモニタを跨る指定は、MoveMouseToVirtual() 関数を使用することで可能です。

MoveMouseRelative(x, y)

マウスポインタを現在の位置を基準として横 (x) ±127, 縦 (y) ±127 の位置に移動させます。

値の指定は整数 -127~127 で行うと分かり易いでしょう。
※ -127~127 を超える指定が無効な訳ではありませんが、0~127 (= 0~127), 128~255 (= -127~0), 256~383 (= 0~127), ... といった規則で割り当てられているだけで、移動できる距離が -127~127 の範囲であることに変わりはありません。

肝心の単位については、G300 で試した限りは px 単位でしたが、正しくはマウスの設定の速度に依存しているらしいです。詳しくは分かりません。

戻り値は nil です。

  1. MoveMouseRelative(-100, 30); -- 左に 100, 下に 30、マウスポインタを移動させます

MoveMouseToVirtual(x, y)

MoveMouseTo() 関数に同じですが、0~65535 の範囲は、マルチモニタ環境における全画面の上端・左端から下端・右端までを表します。

仮にモニタを横並びに三つ並べていたとして、表示の内容もそれに沿うなら、x = 0 は左のモニタの左端を、x = 65535 は右のモニタの右端を指します。

戻り値は nil です。

MoveMouseWheel(click)

マウス ホイールを任意の値分、回します。

正数で奥に、負数で手前に回します。

戻り値は nil です。

  1. MoveMouseWheel(-3); -- 手前に 3 だけ回します。

PlayMacro(macroname)

アクティブなプロファイルに登録されている macroname に指定した名前のマルチキーを実行します。

戻り値は nil です。

AbortMacro()

マルチキーの実行を停止します。キーストロークの途中でも停止します。

※マルチキーの [切り替え] 機能による停止の場合は、キーストローク全体の実行が完了してから停止する、という違いがあります。

戻り値は nil です。

G13 Programming

  • SetMouseSpeed(New mouse speed 32~255) ... 戻り値は nil
  • GetMouseSpeed(Current mouse speed 32~255) ... 戻り値は、エミュレートされたマウスの現在の速度
  • IncrementMouseSpeed(Mouse speed increment) ... 戻り値は nil
  • DecrementMouseSpeed(Mouse speed decrement) ... 戻り値は nil

以上四つは左手用キーパッド G13 でポインタの移動を行うための関数っぽいですが持っていないので詳細不明。

恐らく上から順にポインタの移動速度の変更、取得、加速、減速だと思います。

GetMouseSpeed() の引数はマニュアルからの引用ですが用途不明。サンプルでも引数は使われていませんでした。

その他

Lua 5.1 の標準ライブラリの内、サポートしている関数は次のものだそうです (G-series Lua API V8.45 Overview and Reference の 43 ページ目の「Standard Lua 5.1 Libraries」より)

string

byte(), char(), dump(), find(), format(), gmatch(), gsub(), len(), lower(), match(), rep(), reverse(), sub(), upper()

table

concat(), insert(), maxn(), remove(), sort()

math

abs(), acos(), asin(), atan(), atan2(), ceil(), cos(), deg(), exp(), floor(), fmod(), frexp(), huge(), ldexp(), log(), log10(), max(), min(), modf(), pi(), pow(), rad(), random(), randomseed(), sin(), sinh(), sqrt(), tan(), tanh()

他、基本関数についても概ね使用できました。

OnEvent() 関数の説明

  1. function OnEvent(event, arg[, family])
  2.  -- ここの内容が実行される
  3. end

左ボタン (※1) とホイールの回転を除いた G ボタンを含むマウスボタン, G キー, M キーの押下・押下の解除、当該スクリプトが登録されたプロファイルがアクティブ・非アクティブになった時に、関数の内容を実行します。

※1 EnablePrimaryMouseButtonEvents() 関数によって、左ボタンでも発火するように設定を変更できます。

戻り値はありません。

event には OnEvent() が発火した理由が文字列で、arg には理由の補足が整数で、family には発火させたハードウェアの種類が "kbd" (キーボード), "lhc" (左手用キーパッド), "mouse" (マウス) という文字列の形で代入されます。

event, arg の内容について、詳しくは以下の表を参照してください。

event説明arg説明
"PROFILE_ACTIVATED"当該スクリプトが登録されているプロファイルがアクティブになったため0なし
"PROFILE_DEACTIVATED"当該スクリプトが登録されているプロファイルが非アクティブになったため
"G_PRESSED"G キーが押下されたため1~G キーの番号。G3 キーなら 3
"G_RELEASED"G キーの押下が解除されたため
"M_PRESSED"M キーが押下されたため1~M キーの番号。M1 キーなら 1
"M_RELEASED"M キーの押下が解除されたため
"MOUSE_BUTTON_PRESSED"マウスボタン (G ボタン含む) が押下されたため1~マウスボタンの番号。1 = 左ボタン (≠左クリック), 2 = 右ボタン (≠右クリック), 3 = 中ボタン (≠中クリック), 4 = G4 ボタン, 5 = G5 ボタン, ...
"MOUSE_BUTTON_RELEASED"マウスボタン (G ボタン含む) の押下が解除されたため

OnEvent() 関数を単に複数回定義した場合、後に定義した方で上書きされます。

イベントが発火した場合、イベントの内容が終了するまで、次の発火による実行は待機させ、順次実行していきます。

  1. function OnEvent(e, a)
  2.  OutputLogMessage("%s\n", e);
  3.  Sleep(3000);
  4. end

以上の内容でマウスの右ボタンをクリックすると、ボタンの押下によって発火したことを示す "MOUSE_BUTTON_PRESSED" というログと、押下の解除によって発火したことを示す “MOUSE_BUTTON_RELEASED” というログとが出力される間が 3 秒空きます。

サンプル

索引

マウスのボタンが押された時に、メッセージ (event, arg, family の内容) を出力する

function OnEvent(e, a, f)
	if e == "MOUSE_BUTTON_PRESSED" then
		OutputLogMessage("event = %s, arg = %d, family = %s\n", e, a, f);
	end
end

先ずはメッセージログの出し方を覚えておくと楽です。

G9 ボタンを押している間だけ、次のモードに切り替える

m, hw = 1, "mouse"; -- hw にはデバイスの種類 ("kb", "lhc", "mouse") を入れる

function OnEvent(e, a)
	if a == 9 then
		if e == "MOUSE_BUTTON_PRESSED" then
			m = GetMKeyState(hw);
			SetMKeyState((m == 3 and 0 or m) + 1, hw); -- 3 がモードの総数
		elseif e == "MOUSE_BUTTON_RELEASED" then
			SetMKeyState(m, hw);
		end
	end
end

SAI で言うツール シフト。

記憶した座標を左または右クリックする

t = {[1] = {[8] = {}, [9] = {}}};
-- M1 の G8, G9 ボタンに登録できるようにする、の意
-- 仮に M2 の G4 ボタンを追加したいなら t = {[1] = {[8] = {}, [9] = {}}, [2] = {[4] = {}}} とする

function OnEvent(e, a, f)
	if e == "MOUSE_BUTTON_PRESSED" and a > 3 then -- 処理数を軽減するため、扱うボタンを G4 以降に制限しています
		m = GetMKeyState("mouse");
		if type(t[m]) == "table" and type(t[m][a]) == "table" then
			b = IsModifierPressed("ctrl") and 1 or IsModifierPressed("shift") and 3 or 0;
			ref = t[m][a];
			if b == 0 then
				if # ref ~= 0 then -- 座標が記憶されていなければ何もしない
					x, y = GetMousePosition(); -- 現在の座標の一時記憶
					MoveMouseTo(ref[1], ref[2]);
					PressMouseButton(ref[3]); Sleep(16); -- 余裕がないと右クリックに失敗するアプリケーションがあったので。1 ms で大丈夫っぽいけど不安だから 16 ms に
					ReleaseMouseButton(ref[3]); Sleep(16); -- 余裕がないと次の MoveMouseTo() の実行前に押下を解除できず、ドラッグになってしまう
					MoveMouseTo(x, y); -- 座標を元に戻す
				end
			else
				x, y = GetMousePosition(); -- 座標の登録
				ref[1] = math.max(0, math.min(x, 65535)); -- 座標をプライマリモニタの範囲に収める
				ref[2] = math.max(0, math.min(y, 65535));
				ref[3] = b; -- 左・右クリックの登録
			end
		end
	end
end

Ctrl または Shift キーを併用して G ボタンを押すと現在のマウスポインタの座標を記憶し、次回 G ボタンを単独で押した際に、記憶した座標を左または右クリックします。Ctrl キーを併用して記憶したなら左クリック、Shift キーを併用して記憶したなら右クリックになります。

SAI でパレットやキャンバス上から色を簡便に拾うために書きました。

マルチモニタ環境は想定していないと言うより対応できませんでした。GetMousePosition() が -1 以下 65,536 以上を超える値を返すのだから MoveMouseTo() にも同じ値が指定できれば片付くのだけれど。MoveMouseToVirtual() で対処するには、モニタの数及び配置を知る手段が必要な気がしますが、算数もロクにできない私には判断付きませんでした。

マウスの X1 (戻る) ボタンが押されている間だけ、マウスポインタの移動でホイールの回転を行う

function OnEvent(event, arg)
	local src, des, a = {GetMousePosition()}; -- 初期座標を得る
	while IsMouseButtonPressed(4) do -- マウスの X1 ボタンが押下されている限りループ
		des = {GetMousePosition()}; -- 新しい座標を得る

		a = src[2] - des[2]; -- 差を得る
		if math.abs(a) > 256 then -- ある程度の差がなければ無反応
			a = a / 1024; -- 減衰
			MoveMouseWheel(a > 0 and math.floor(a + 0.5) or math.ceil(a - 0.5)); -- 四捨五入した値でホイールの回転
		end

		src[2] = des[2]; -- 比較元の更新
		Sleep(64);
	end
end

意味はありません。

いや、本当は SAI で戻る・進むボタンが無意味だったのと、物理ホイールとは別にホイることができたら幅が広がるのではって予感がビビビッと来た結果書いたのですが、用途がこれっぽっちも思い浮かびませんでした。
X1 に Ctrl, X2 に Shift 当ててホイール回した方がよくねって感じです。戻る・進むが機能するアプリケーション上だと鬱陶しいだけだし。

と言うか、基本的なマウス機能の押下をチェックできる関数はあるのに、G ボタンに対してのそれがないのが残念。

X1 (戻る)・X2 (進む) ボタンの長押しで Ctrl+Z・Ctrl+Y を実行する

function OnEvent(e, a)
	if e == "MOUSE_BUTTON_PRESSED" then
		local s, n = {{4, "lctrl", "z"}, {5, "lctrl", "y"}}; -- set = {{button, key1, key2, ...}, ...}
		n = # s;

		while n > 0 do
			local ms, i, f = 0, 96, false; -- millisecond, interval, flag

			while IsMouseButtonPressed(s[n][1]) do
				if not f then
					if 256 > ms then -- 経過時間が 256 ms 未満なら、変数 ms に一周あたりの Sleep 時間 i を加算する
						ms = ms + i;
					else
						PressKey(s[n][2], s[n][3]); -- 既定の時間が経過したなら、キーを押下状態にする
						f = true;
					end
				end

				Sleep(i);
			end

			if f then ReleaseKey(s[n][3], s[n][2]); end -- キーの押下を解除する

			n = n - 1;
		end
	end
end

戻る・進むをキャンセルする訳ではないので、例えば Opera で使うと、ボタンの押下を終えた時に戻る・進むも一回実行される。G ボタンさえ ry

inserted by FC2 system