情報科学屋さんを目指す人のメモ(FC2ブログ版)

何かのやり方や、問題の解決方法をどんどんメモするブログ。そんな大学院生の活動「キャッシュ」に誰かがヒットしてくれることを祈って。

ブログ内検索

スポンサーサイト このエントリーを含むはてなブックマーク

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
スポンサー広告 | 編集

ひらがなカタカナキーをF21キーに変更 このエントリーを含むはてなブックマーク

AutoHotkeyのスクリプトを書いていると、ひらがなカタカナキーがDownされたっきりUpされないという事態に。そこで、「ChangeKeyを使用してWindowsキーをF13キーに変更する方法」を利用して、ひらがなカタカナキーをF21キーにして問題解決。

ちなみに、キーの履歴を見ると、ひらがなカタカナキーとして「vkF0sc070」と「vkF2sc070」が表示されており、UpとDownで異なる表示がされていました。ここらへんが何か関係あるのかも。

このキーと同じように、CapsLock、半角/全角も扱いにくいキーですが、ChangeKeyで他のキーと置き換えてからカスタマイズする分にはそれほど問題にならない、はず。

スポンサーサイト
AutoHotkey | コメント:2 | トラックバック:0 | 編集

AutoHotkeyで、ちょっと高機能な「行頭へカーソルを移動」を作ってみる このエントリーを含むはてなブックマーク

インデントされている文章を編集しているときに、Homeキーなどで単純に行頭へカーソルを移すと、本当に編集したい"行頭"までTabやスペースの分だけ右に移動しなければなりません。今回は、インデントのTabやスペースを認識して、その手前まで移動するホットキー「行頭へカーソルを移動」を、AutoHotkeyを利用して作成します。また、それを通して、AutoHotkeyを利用するときのコツを紹介します。

文字列の内容を知るためには、コピーするしかない

今回は、Tabや半角スペースの存在をAutoHotkeyScriptが認識しなくてはいけません。このように、カーソル付近の文章を認識するためにはその内容をクリップボードにコピーして、それを読み込む必要があります

このとき、現在のクリップボードの内容を一時的に退避して、作業が終わったら戻す必要があります。実は、この作業には、いくつかの注意すべきポイントがあります。

選択範囲の内容を読み取る方法

行頭へ移動するホットキーを作る前段階として、選択した文字を変数に格納してみます

カーソルの一文字左を読み取るコードは次のようになります。

^j::
	; クリップボードの内容を退避
	clipboard_backup = %ClipboardAll%

	: 選択
	Send +{Left}

	; コピー
	Clipboard = ; クリップボードを空にする
	Send ^c     ; 実際のコピーコマンド
	ClipWait, 1 ; コピー完了まで待機

	; 変数へクリップボードの内容を格納
	selected := Clipboard

	; 表示
	msgbox, %selected%

	; クリップボードの内容を復元
	Clipboard := clipboard_backup

	Return

見ての通り、結構長くなります。ただ、この中に注意すべき点がたくさんあるのです。以下、注意点を一つ一つ説明しておきます。

クリップボードの内容を退避と復元で利用する変数が違う

ClipboardAll変数は、退避のために利用する変数です。このコードのように「ClipboardAll」変数を利用して、バックアップ先の変数に退避してクリップボードを使う作業を終えたら、今度は「Clipboard」変数にその内容を代入します。ここで、ClipboardAllに代入しても無意味です。ClipboardAll変数は、退避専用の変数です

ClipWaitを利用するために、コピーの前にClipboardを空にする

「Send ^c」の前に、「Clipboard =」でClipboard変数の中身を空にしています。これをしないと、次に紹介するClipWaitコマンドが意図した動作をしてくれません。かならずコピーの前にはClipboard変数をクリアしておきましょう。

コピーの完了をClipWaitで確認する

選択範囲のコピーの実際は、単なる「Send ^c」です。つまり、このキー入力を受け取ったアプリケーションがクリップボードに選択範囲の文字列を格納してくれるということを意味します。つまり、「Send ^c」をした直後、すぐクリップボードの内容が更新されているわけではなく、コピーの完了を待たなければならないということです。そこで利用するのが「ClipWait」コマンドです。

「ClipWait, 1」では、最大1秒、クリップボードの更新を待ちます。このとき、実際には、テキストとして読み取れる内容になることを待つので、あらかじめ内容をクリアしておく必要があるわけです。

クリップボードの内容を利用するときはClipboard変数

クリップボードの内容を利用するときは、「ClipboardAll変数」ではなく、「Clipboard変数」を利用してください。ClipboardAllを使って読み出しても、テキストとして利用できません。

行頭へ移動ホットキー(低速版)

では、選択範囲の読み出し方法が分かったところで、実際に目的のホットキーの実装を行います。今回は、とりあえず行頭までジャンプして、右隣がTabか半角スペースだったらひとつ移動するようにしてみます。

実際のコードは次のようになります。

^j::
	; 退避
	clipboard_backup = %ClipboardAll%

	; 先頭へ移動
	Send {Home}

	; カーソル位置の修正用ループ
	Loop {
		; カーソルの一つ右の文字を読み取る
		Send +{Right}
		Clipboard :=
		Send ^c
		ClipWait, 1
		selected := Clipboard

		; インデント文字かどうかで分岐
		If (selected = " " || selected = "`t") {
			Send {Right} ; 次の文字へ
		} Else {
			; 選択を解除して抜ける
			Send {Left}
			Break
		}
	}

	; 復元
	Clipboard := clipboard_backup

	Return

このコードは、とりあえず目的のとおり動きます環境、特にアプリケーション次第でうまくいかないかもしれません。今はとりあえずTeraPadで試しています。ただ、半角スペース8つなどのインデントで試しに実行してみると、まるでスローモーションです。

この原因のひとつは、コピー回数が多いことです。

行頭へ移動ホットキー(中速版)

次に紹介するコードは、コピー回数を減らしたバージョンです。

^j::
	; 退避
	clipboard_backup = %ClipboardAll%

	; 先頭まで選択
	Send +{Home}

	; 選択範囲を読み取る
	Clipboard :=
	Send ^c
	ClipWait, 1
	selected := Clipboard

	; クリップボードの内容を復元
	Clipboard := clipboard_backup

	; 選択範囲一文字ずつに対してループ
         Loop % StrLen(selected) {
		; 左から順番に一文字取り出す
		c := SubStr(selected, A_Index, 1)
		
		; インデント文字かどうかで分岐
		If (c = " " || c = "`t") {
			Send +{Right} ; 選択範囲を狭めて次の文字へ
		} Else {
			Break ; 終了
		}
	}

	; 選択を解除
	Send {Left}
	Return

これでも十分遅いのですが、前のバージョンよりは速くなっています。このように、できるだけClipWaitで待つ時間を小さくした方がよいと思われます。ちなみに、今回のバージョンで最後の「Send {Left}」をコメントアウトすると、「先頭まで選択」ができます。

もっと速くするためには

実は、遅い原因の大部分はカーソル移動時間です。一文字ずつカーソルを移動させる限り、カーソル移動にかかる時間がどうしても削れません。そこで、「Ctrl+→」などを使って移動すればもっと高速化できるのですが、アプリケーションの依存度が高く、アプリケーションごとにどこまで移動するかが変わってしまうため、ちょっと微妙です。参考として、少し動作が変わってしまいますが(メモ帳ですら不適合で、TeraPadでわりと意図したとおり動いたという程度)、その一例を載せておきます。

^j::
	; 退避
	clipboard_backup = %ClipboardAll%

	; 先頭まで選択
	Send +{Home}

	; 選択範囲を読み取る
	Clipboard :=
	Send ^c
	ClipWait, 1
	selected := Clipboard

	; クリップボードの内容を復元
	Clipboard := clipboard_backup

	; 先頭の一文字を取り出す
	c := SubStr(selected, 1, 1)

	; インデント文字かどうかで分岐
	If (c = " " || c = "`t") {
		Send ^+{Right} ; 単語単位の移動を利用して移動
	}

	; 選択を解除
	Send {Left}
	Return

これは、「先頭までを選択」が行いやすいバージョンで、次は、行全体の選択を避けたバージョンです。

^j::
	; 退避
	clipboard_backup = %ClipboardAll%

	; カーソルが先頭になるように、
	; 先頭一文字を選択
	Send {Home}{Right}+{Home}

	; 選択範囲を読み取る
	Clipboard :=
	Send ^c
	ClipWait, 1
	selected := Clipboard

	; クリップボードの内容を復元
	Clipboard := clipboard_backup

	; 先頭の一文字を取得
	c := selected

	; インデント文字かどうかで分岐
	If (c = " " || c = "`t") {
		Send ^{Right} ; 単語単位の移動を利用して移動
	} Else {
		Send {Left}
	}
	Return

まとめ

AutoHotkeyを使うとこんな感じで作業を自動化できますよ、という紹介にはなったと思います。ただ、そんなことより重要なのは、Clipboardの使い方です。いろいろ注意点が多いので、気を付けてください。

AutoHotkey | コメント:0 | トラックバック:0 | 編集

MS Office用のAutoHotkeyスクリプトを書くときの注意 このエントリーを含むはてなブックマーク

MS Office、ExcelやWord、OneNoteなどを利用する人には、専用AutoHotkeyスクリプトの作成をおすすめします。作業効率を大きく上げることが可能です。

しかし、設定したはずのホットキーがうまく働かないことがあります。

たとえば、Excelでホットキーから「Send {Home}」や「Send ^+`;」をしたり、OneNoteでホットキーから「Send {Down}」や「Send {Up}」をしようとすると、うまく動きません。

AutoHotkey | コメント:3 | トラックバック:0 | 編集

AutoHotkeyで無変換+数字をファンクションキー(F1-F10)にする方法 このエントリーを含むはてなブックマーク

AutoHotkeyで修飾キー(Ctrl,Shift,Alt,Win)の状態(^!+#)を取得する関数を作る方法」で作成したget_modifiers関数と、「AutoHotkeyで変数名を組み立てて変数の中身を取得するちょっと不思議な方法」で作成したget_postfix_key関数を利用して、無変換+数字をF1-F10に割り当ててみます

無変換+数字をFキーに割り当てるAutoHotkeyスクリプト(.ahk)

コードは以下の通りです。

~vk1Dsc07B & 1::
~vk1Dsc07B & 2::
~vk1Dsc07B & 3::
~vk1Dsc07B & 4::
~vk1Dsc07B & 5::
~vk1Dsc07B & 6::
~vk1Dsc07B & 7::
~vk1Dsc07B & 8::
~vk1Dsc07B & 9::
~vk1Dsc07B & 0::
	postfix_key := get_postfix_key()
	if postfix_key = 0
		postfix_key := 10
	modifiers := get_modifiers()
	Send, %modifiers%{F%postfix_key%}
	return

get_modifiers() {
	modifiers := ""
	if GetKeyState("Ctrl", "P")
		modifiers = %modifiers%^
	if GetKeyState("Shift", "P")
		modifiers = %modifiers%+
	if GetKeyState("Alt", "P")
		modifiers = %modifiers%!
	if GetKeyState("Win", "P")
		modifiers = %modifiers%`#
	return %modifiers%
}

get_postfix_key()
{
	StringSplit, hotkey_array, A_ThisHotkey, %A_Space%&%A_Space%
	StringTrimLeft, postfix_key, hotkey_array%hotkey_array0%, 0
	Return postfix_key
}

「vk1Dsc07B」は無変換キーを表していますここでは仮想キーコードとスキャンキーを両方書いていますが、片方で良いかもしれないです

get_postfix_key()では、prefixkey(無変換キー)と同時に押したキー(0,1,...,10)を検出しています。これにより、無変換+数字に対して一貫したコードを記述できています。

また、このようなコンビネーションキーを記述した場合、CtrlやShiftを表す^や+などの修飾キーを「::」の前に含めることが出来ないので、get_modifiers()を利用してCtrlやShiftの状態を取得しています。

このようにして、get_postfix_keyとget_modifiersを使用することできれいに「無変換+数字→ファンクションキー」を実現できています。

Windowsダンプの極意 エラーが発生したら、まずダンプ解析!
Advanced Windows 第5版 上 (マイクロソフト公式解説書)
インサイド Microsoft Windows 第4版〈上〉 (マイクロソフト公式解説書)
APIで学ぶWindows徹底理解

AutoHotkey | コメント:0 | トラックバック:0 | 編集

AutoHotkeyで修飾キー(Ctrl,Shift,Alt,Win)の状態(^!+#)を取得する関数を作る方法 このエントリーを含むはてなブックマーク

modifier(修飾キー)を取得する

押し下げ状態は、GetKeyStateで取得できます。今回は、その結果を、Sendの引数として利用できる形式(^、+、!、#の結合)で取得する関数get_modifiers()を作成します

get_modifiers()

定義は次の通り。

get_modifiers() {
	modifiers := ""
	if GetKeyState("Ctrl", "P")
		modifiers = %modifiers%^
	if GetKeyState("Shift", "P")
		modifiers = %modifiers%+
	if GetKeyState("Alt", "P")
		modifiers = %modifiers%!
	if GetKeyState("Win", "P")
		modifiers = %modifiers%`#
	return %modifiers%
}

現在キーボードのWinキーをF17キーに変更してしまったのでWinキーについては試せていませんが、他の修飾キーに関しては問題なく動作しています。

modifiers := get_modifiers()
Send, %modifiers%{%key_name%}

のようにして、利用できると思います。特に「AutoHotkeyで変数名を組み立てて変数の中身を取得するちょっと不思議な方法」などと組み合わせるといろいろ出来ると思います。お試しあれ。

Windowsダンプの極意 エラーが発生したら、まずダンプ解析!
Advanced Windows 第5版 上 (マイクロソフト公式解説書)
インサイド Microsoft Windows 第4版〈上〉 (マイクロソフト公式解説書)
APIで学ぶWindows徹底理解

AutoHotkey | コメント:1 | トラックバック:0 | 編集
 | HOME |  OLD >>
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。