中小企業で生きていくシステムエンジニアが考えるライフハック・ITツール・投資、人生100年を生き抜く人生戦略、生産性向上をノリックが考える

中小企業で働くシステムエンジニアがライフハック、ツール、投資、人生100年を生き抜く人生戦略、生産性向上を語ります

Autohotkeyに関する記事で1万字超えの記事を書き、 Google からの検索流入が一か月後に増加するかどうかを確認しつつ、タイトルはやっぱり長い方が良いのかも検証する

www.mmbomber.com

購読しているのっぶさんのブログによると一万字の記事を書いた一か月後に Google さんからの検索流入増加したとのことであった。この記事を見て私もやろうと思っていたのだが面倒くさくて後回しにしていたのである 。しかしのっぶさんが更に以下の記事の公開があったため、どうせだったらまとめて検証しようと思った次第である。

www.mmbomber.com

 

なぜオートホットキーに関する記事かと言うと、ソースコードも貼り付けることになるから単純に文字数を稼げるのではないかと下心である。しかし、一万字もあるとはてなブログの編集がとても重いぞ。これは改善してほしい点だ。

AutoHotKey

 

 Autohotkeyとは

ショートカットを自由自在にカスタマイズ出来るツールと思っている。あと、アプリ間の連携もある程度可能だ。GUIアプリも作れるが自分はやったことが無い。GUIやるならVB.netでやるかとも思うが、.net Frameworkがなくても出来るので意外とお手軽という話もある。

 

AutohotkeyのWiki

迷ったら参照するページだ。

http://ahkwiki.net/Top

 

Autohotkeyのインストール

https://autohotkey.com/download/

AutoHotkey 1.1.* 版をインストールすることを進める。Unicode版なので日本語を扱う上ではこちらのほうが良いのではと思っている。Ver2.0はα版となっているため、試したことはない。しかし、どんな機能が増えているのかは興味が湧いてきたので時間がある時に調べてみよう。→タスクペディアに登録済み。

 

Autohotkeyスクリプトファイルを作る

とりあえずマイドキュメントにAutohotkeyのスクリプトファイルを作成する。最初はマイドキュメントにでも作っておけばよいだろう。右クリックしてテキストファイルを作成する

C:\Users\{ログインユーザー名}\Documents\



基本のキーリマップ

私が使用しているリマップは以下の通りだ。

・・・・

 

と思ったらリマップの機能つかってなかった。orz

こんなことは普段は書かないが、心の中の叫びを書いていかないと一万字到達は厳しい。ただ、一つリマップぽいことをしていた。

以下のコードの意味はF1キーを押したら何もしない(Return)ということだ。Autohotkeyがなかった時代はMicrosoft OfficeでEscキーを押すつもりが誤ってF1キーを押してしまい、今は亡きイルカが「なにか御用ですか?」とアニメーションしながら出てくるのが非常にうっとおしかったのである。そのため、キーボードを魔改造しF1キーを破壊するという事をしていたが、Autohotkeyを知ってからはそのような事をする必要がなくなった。

以下の例でわかったと思うが、Autohotkeyにおけるコメント文はセミコロン(;)だ。

コード1

 

;F1の無効化 ###################

F1:: return


myscript.ahkとして保存だ。ファイル名は適当で良い。そしてダブルクリックするとタスクバーのところにHマークのアイコンが有ることを確認する。そしてエクセルを起動しF1キーを連打する。通常であればノロノロとヘルプ画面が出てくるが何回叩こうが出てこない。もうこれだけで、今年新卒でシステムズエンジニアになってしまった人は定年するまでに1人月分ぐらいの無駄な時間を過ごさなくて済むだろう。とりあえず上記を書いたらマイドキュメントに

 

ショートカットをスタートアップに入れておこう

AutohotkeyのスクリプトはWindows起動時に立ち上がるようにしておこう。でないとせっかくカスタマイズしたショートカットが有効にならずに生産性を落とすことになってしまう。

 Winキー+r で 「Shell:startup」と入力すればスタートアップフォルダを開くことが出来るぞ。私はこれを一年ほど前に知ったので社会人生活の中でスタートアップフォルダを探すために1人月は損をしている気がする。さっきのF1キーを無効化にするのと合わせてドローだ。

 

ホットストリングを使う

ホットストリングというのはあるキータイプをしたら自動的に何かをするというものだ。何を言っているのかわからないと思う。以下コード2の例は「nog」とタイプし、セミコロンを入力するとメールアドレスに変換する例である。

コード2

;メールアドレスの入力###############
:O:nog::no.matsumoto@gmail.com
Return
:O:nos::no.matsumoto@i.softbank.jp
Return



さらに以下のコード3はメールの書き出しでいつも書く「お世話になっています。」だ。

ちなみに以下のスクリプトを事細やかに、うっとおしいぐらいに解説すると

2行目でクリップボードに文字列を格納している。`nは改行だ。

3行目はちょっと待機。

4行目はCtrl+v つまりよく使うクリップボードから貼り付けるというショートカットキーを送り込んでいる。そして{up}は上矢印、{Left}は左矢印で何をしたいかというと、様の前にカーソルを移動しているのである。そして相手の名前は手入力する。

コード3

:O:osewa::
Clipboard = 様`nお世話になっています。松本です。`n
Sleep 100
Send,^v

Send,{Up}{Left}

Return

ん? そんなのimeに辞書登録をしておけば良いんじゃねえの?と思った新人システムズエンジニアがいれば君は出来るやつだ。私もそうしていた。だがしかし、今は一台のパソコンしか持っていない新人SEにも、そのうちポジションが上がってくると打ち合わせ用のノートPCが支給されたり、外出用時に持ち出すセキュリティ設定がされたノートPCを支給されたりする。更に最近はリモートワークが流行りのため、家のPCでも仕事をしないといけなかったり、家からセキュリティで保護された仮想環境に入ったりして一人でいくつもの環境を持つようにそのうちなるのだ。なぜGoogle IMEが辞書を端末間で共有してくれないのか不思議なのだが、その都度辞書ファイルをエクスポート・インポートするのは煩わしいのである。Autohotkeyスクリプトにすべて集約できるのなら端末が増えた時の対応も迅速に行える。だが、スマホにはAutohotokeyが無いので辞書登録で耐えている。 

 

メールを制するものは仕事を制す

私の前の職場では大規模プロジェクトであったため、メールが一日に2~300通は来ていた。メールの先頭の方をみて「マツモトさんへ」の「マツ」が見えなかったらDeleteキーを押していたぐらい速攻で自分が見る必要のあるメールかどうかを判断しなければならなかった。なのでメールがすばやくさばけるかどうかは、システムズエンジニアの生死に関わってくる問題なのである。

 あまりメールを長時間返さないと、Skypeで在籍してPCを触っていると他の人に「在籍中ですよ」と通知する非常に迷惑な機能があり、電凸されてしまう。そうなったらもっと時間をロスしてしまうのだ。

 多少前置きが長くなったことはご容赦願いたい。なんと言っても今回の記事は1万字を超えることを目標としているのである。

 エクセルでお気に入りのショートカットキーにCtrl+;(セミコロン)で日付を挿入できるというものがある。愛用している人も多いであろう。しかしこれになれてくると何故このショートカットキーを他のアプリでも採用しないのか、他のアプリ開発の人もAutohotkeyにまかせておけばいいじゃないかと思っているかはは謎だが、少なくともメールでは今日の日付を挿入したい場面はよくあるだろう。

 以下のコード4はCtrl+Shift+;(セミコロンを)入力すると日付を入力してくれるスクリプトである。他のアプリでも使いたいと思ったらクラス指定でどんどん増やしていけばよいだろう。

コード4

;エクセル以外でもCntr+Shift + ;で日付入力
^+;::
FormatTime,TimeString,,yyyy/MM/dd
Send,%TimeString%
Return


メールにファイルのフルパスが書かれているのを開く

メールにレビューして欲しいドキュメントのファイルサーバーフルパスを記入して受け取ることがあるだろう。仕事の遅いやつはメールに書かれているアドレスを見ながら自分でエクスプローラを開いていく。ちょっと出来るやつはWin+Rのショートカットキーでファイル名を指定して実行を開き、メールに書かれているパスをクリップボードをコピー&ペーストしてフィアルを開く。もっと出来るAutohotkey使いはファイルパスをコピーすると同時に開く。

 たまに気を利かしてディレクトリの最後で改行してファイル名を別行に書いてくる人がいるが、それだとフォルダを開いてメールに書かれているファイルをクリックする必要がある。それも面倒なので下のコード5では複数行を選択してコピーしたファイルパスから改行を除去している。

そしてA/SRというファイラーを介して開くようにしてている。そうすればフォルダのパスだったらA/SRで該当のフォルダを開くことが出来るし、もしファイルのフルパスだったら関連付けたアプリケーションで当該ファイルを開いてくれる。

コード5

;Ctrl + Shift + o でAs/Rでクリップボードのパスを開く(メールでパスを貰ったときとか
^+o::

;改行を除去する。
str = %clipboard%
str := RegExReplace(str , "\n|\r","")
Run,C:\Asr\AsrLoad.exe %str%

Return


一昔前であればメールを返信すると前のメールの先頭に「>」が勝手について、その引用文の下にコメントを付けて返信していたものである。ところが時代は進み、今やほとんどのメールがHTML形式で送受信されるようになった。Outlookで返信すると前のメールに縦線が入るのだが、先方が出してきたメールの一部分を引用して返信したい時に先頭に「>」をつけてしまいたいときがある。仕事のできないやつは手入力で先頭に一行ずつ「>」をつけていく。ちょっと仕事が出来るやつはテキストエディタの矩形選択とかで先頭に>を一括でつける。もっと仕事が出来るAutohotkey使いだったらショートカットで一発である。


メールの引用

コード6

;Ctrl+Shift+>でコピーした内容に>を先頭に追加する。
^+>::
add = >
strbk = %clipboard%
str = %clipboard%
Loop, Parse, str, `n
{
if str_row =
str_row = %add%%A_LoopField%
else
str_row = %str_row%`n%add%%A_LoopField%

}
clipboard = %str_row%
Send,^v
Sleep 60
clipboard = %strbk%
str = 
strbk = 
str_row =
Return

エクセルを制するものは仕事を制す


 システムズエンジニアというのはエクセルでドキュメントをこれでもかというぐらい書かなければならない。もちろんエクセルでドキュメントを書くなんぞもっての他という批判があるもの承知の上なのだが、数百人メンバーが居るようなプロジェクトで

「今回のドキュメントはMarkDownでやりましょう。図が必要であればPlantUMLで!」

なんか言っても、分かる人が数人いれば良いぐらいである。必然的にみんなが使えるエクセルでドキュメントを作るのが全体としては一番生産性が高い結果になると思う。

 

 そしてエクセルはショートカットを駆使すればするほど生産性が上がるナイスなソフトである。プロジェクターでエクセル捌きを他のメンバーに見せつければ、それだけで尊敬の眼を向けてくれる人は数人いる。というわけでエクセルのショートカットは覚えるしか無いのだが、それでもまだ足りないものがある。これはAutoHotKeyで補完するしか無い。

 

くどいかもしれないが、以下のコード7についても事細やかに解説するぞ。

#IfWinActive だが、この一行があるとエクセルでしか、If文内で定義したショートカットキーは有効にならない。冒頭に紹介したF1無効化もエクセルのみに適用したい場合はこのIF文の中にF1::Return と定義してしまえばエクセル以外ではF1キーを有効にできるのである。しかしなんとなく「XLMAIN」というのがエクセルを表すことはわかると思うが、どうやってそんな事調べるんだ?と思った人は鋭い。

 そんなことはAutohotkey作った人も当然考慮済みでスタートメニューのAutohotokeyの中にWindows Spyというかっこいい名前のプログラムがある。これを立ち上げて自分があやつりたいアプリをクリックすれば、それがどんなクラス名か判別できるのである。

 

というわけで上述したメーラーで使うショートカットキーもメールアプリケーションでだけ有効にするということがもちろん可能だ。Windows Spyを使ってぜひご自身で使われているメーラーがどんなクラス名か確認して欲しい。

 

エクセルのコピペを極める

 エクセルではコピー&ペーストする作業が多発する。しかし単純にCtrl+cとCtrl+v しか使っていないのであれば、エクセル初心者である。メニューからマウス使って形式選択で貼り付けを選んでいるのもシステムズエンジニアっぽくない。ではどうするかというとAltキー、h、v、s と順番に入力していくとメニューをたどれるのである。私はこのメニューのたどり方をOffice95の時に覚えてしまったのだが、Officeのメニューがリニューアルした時に、Altキーでのたどり方も変わってしまった。だが、古いたどり方を覚えている人のためにマイクロソフトは親切にも昔のたどり方でも使えるようにしているのだ。これから覚える人はまずはAltキーを押してメニューに出てくるアルファベットをみながらたどると良いだろう。以下のコード7の二つ目はセルの中で折り返す書式設定をしている。これは、現在が折り返しの設定になっていれば折返しを解除するし、折返ししない状態になっていると折返し設定にしてくれるので便利である。Ctrl+1でメニューを起動するより速い。

コード7

;エクセルの処理
#IfWinActive , ahk_class XLMAIN
{

^+v::Send,!hvs ;形式を選択して貼り付け
^+r::Send,!hw ;折り返し表示

^+0::Send,^1{Tab}{Down}{Enter} ;数値書式にする
Return

}

#IfWinActive

 

エクセルの行挿入、行削除を極める

 エクセルを使っていると行や列の挿入、コピーした行や列の挿入をしたいことが頻繁になるだろう。Shift+SpaceやCtrl+Spaceで行や列を選択してCtrl++(Ctrlキーを押しながらテンキーの+(プラス))で行や列の追加が出来る。ところが日本語圏の我々には困った問題がある。IMEがONの状態だとShift+Spaceを押すと半角スペースが入っていしまうのである。なので毎度日本語入力をOFFにする必要がある。しかしそんな事をいちいち気にしていられるほどシステムズエンジニアは日まではないのである。ということはAutohotkeyの出番である。Autohotkeyが登場以来、日本でこれほど広まったのはIMEの制御が出来るというのが大きな要因ではないかと思っている。

 以下のコード8を見るとIME_Get()という関数が使われているのがわかる。これはかつてAutohotkey神が地上にもたらした関数である。

 これをC:\Program Files\AutoHotkey\IME.ahk に配置しておく。Autohotkeyをインストールした場所なのだが、わからなくなってしまった人はスタートメニューのAutohotkeyから右クリックしその他→ショートカットファイルの場所を開くでショートカットフォルダを開いててからさらにWindows Spyのショートカットを右クリックするとインストールした場所がわかるぞ。そこに下記のIME.ahkを放り込んでおけば、IMEに関する関数が別のahkファイルからも使いたい放題だ。

 

 コード8の解説に移るぞ。Shift+Spaceキーが押された時にIMEの状態を取得し、もし日本語入力がOFFだったらShift+Spaceキーを送り込み、日本語入力がONだったら、日本語入力をOFFにしてからShift+Spaceキーを送り込んでいる。非常に行選択が快適になるはずだ。

コード8

;エクセルの処理
#IfWinActive , ahk_class XLMAIN
{


;エクセルでIMEの制御を考慮した行選択
+Space::  
getIMEMode := IME_Get()  
if (%getIMEMode% = 0)  
{  
   
   Send,+{Space}
   return  
}  
else  
{  
IME_SET(0)
Sleep 30
Send,+{Space}
Sleep 30
IME_SET(1)
return  
}  
Return
}

#IfWinActive


IME.ahk

/**************************
 IME制御用 関数群 (IME.ahk)

   グローバル変数 : なし
   各関数の依存性 : なし(必要関数だけ切出してコピペでも使えます)

   AutoHotkey:     L 1.1.08.01
   Language:       Japanease
   Platform:       NT系
   Author:         eamat. http://www6.atwiki.jp/eamat/
***************************
履歴
   2008.07.11 v1.0.47以降の 関数ライブラリスクリプト対応用にファイル名を変更
   2008.12.10 コメント修正
   2009.07.03 IME_GetConverting() 追加 
              Last Found Windowが有効にならない問題修正、他。
   2009.12.03
     ・IME 状態チェック GUIThreadInfo 利用版 入れ込み
      (IEや秀丸8βでもIME状態が取れるように)
       http://blechmusik.xrea.jp/resources/keyboard_layout/DvorakJ/inc/IME.ahk
     ・Google日本語入力β 向け調整
       入力モード 及び 変換モードは取れないっぽい
       IME_GET/SET() と IME_GetConverting()は有効

   2012.11.10 x64 & Unicode対応
     実行環境を AHK_L U64に (本家およびA32,U32版との互換性は維持したつもり)
     ・LongPtr対策:ポインタサイズをA_PtrSizeで見るようにした

               ;==================================
               ; GUIThreadInfo 
               ;=================================
               ; 構造体 GUITreadInfo
               ;typedef struct tagGUITHREADINFO {(x86) (x64)
               ; DWORD   cbSize;                0 0
               ; DWORD   flags;                4 4 ※
               ; HWND hwndActive;             8 8
               ; HWND hwndFocus;             12 16 ※
               ; HWND hwndCapture;           16 24
               ; HWND hwndMenuOwner;         20 32
               ; HWND hwndMoveSize;          24 40
               ; HWND hwndCaret;             28 48
               ; RECT rcCaret;               32 56
               ;} GUITHREADINFO, *PGUITHREADINFO;

     ・WinTitleパラメータが実質無意味化していたのを修正
       対象がアクティブウィンドウの時のみ GetGUIThreadInfoを使い
       そうでないときはControlハンドルを使用
       一応バックグラウンドのIME情報も取れるように戻した
       (取得ハンドルをWindowからControlに変えたことでブラウザ以外の大半の
       アプリではバックグラウンドでも正しく値が取れるようになった。
       ※ブラウザ系でもアクティブ窓のみでの使用なら問題ないと思う、たぶん)

*/

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
;
; 動作確認用 内部ルーチン (マウスカーソル位置のウィンドウのIME状態を見る)
;  単体起動時のテスト用なので削除しても問題なし
_ImeAutoExecuteSample:
   Hotkey,#1,_ImeGetTest
   Hotkey,#2,_ImeSetTest
   Hotkey,#3,_ImeIsConvertingTest
   Hotkey,+ESC,_ImeTestExt
   SetTimer,_ImeInfoTimer,ON
return

;--- IME状態表示タイマ ---
_ImeInfoTimer:
   Tooltip,% "IME_GET : "     . IME_GET(_mhwnd())             . "`n"
         . "IME_GetConvMode : " . IME_GetConvMode(_mhwnd())     . "`n"
         . "IME_GetSentenceMode : " . IME_GetSentenceMode(_mhwnd()) . "`n"
         . "IME_GetConverting : "     . IME_GetConverting(_mhwnd())
return

;--- IME Get Test [Win]+[1] ---
_ImeGetTest:
   MsgBox,% "IME_GET : "     . IME_GET(_mhwnd())             . "`n"
         . "IME_GetConvMode : " . IME_GetConvMode(_mhwnd())     . "`n"
         . "IME_GetSentenceMode : " . IME_GetSentenceMode(_mhwnd()) . "`n"
return
;--- IME Get Test [Win]+[2] ---
_ImeSetTest:
   MsgBox,% "IME_SET : "     . IME_SET(1,_mhwnd())             . "`n"
         . "IME_SetConvMode : " . IME_SetConvMode(0x08,_mhwnd())  . "`n"
         . "IME_SetSentenceMode : " . IME_SetSentenceMode(1,_mhwnd()) . "`n"
return

_mhwnd(){ ;background test
MouseGetPos,x,,hwnd
return "ahk_id " . hwnd
}

;------------------------------------------------------------------
; IME窓のクラス名を調べるテストルーチン
;   入力or変換状態でIme窓にマウスカーソル持ってって [Win]+[3]押す
;   Clipboardに Class名がコピーされる。入力窓/候補窓 それぞれ調べる。
;   調べたクラス名は 正規表現になおして
;      IME_GetConverting("A","入力窓クラス","候補窓クラス")
;   とかやって使う。(もしくは IME_GetConverting()の中に直接追加する)
;
;   あああ   ← 入力窓の上に マウスカーソル持ってって [Win]+[3]押す
;    ̄ ̄ ̄      Clipboardに Class名がコピーされる。
;                ※ MS Office系のシームレス入力状態では取れないっぽい
;                   DetectHiddenWindows,ONでもダメ。シームレスOFFにしないと無理
;
;   愛
;  |愛   | ← 候補窓の上にマウスカーソル持ってって [Win]+[3]押す
;  |亜依  |    Clipboardに Class名がコピーされる。
;  |あい  |
;  |藍   |
;  | :  |
;   ̄ ̄ ̄ ̄
;------------------------------------------------------------------
_ImeIsConvertingTest:
   _ImeTestClassCheck()
return
_ImeTestClassCheck()  {
   MouseGetPos,,,hwnd
   WinGetClass,Imeclass,ahk_id %hwnd%
   Clipboard := Imeclass
   ;IME_GetConverting() 動作チェック & IME 入力窓/候補窓 Class名確認
   MsgBox,% Imeclass "`n" IME_GetConverting()
}
;--- 常駐テスト終了 [Shift]+[ESC] ---
_ImeTestExt:
ExitApp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

;---------------------------------------------------------------------------
;  汎用関数 (多分どのIMEでもいけるはず)

;-----------------------------------------------------------
; IMEの状態の取得
;   WinTitle="A"    対象Window
;   戻り値         1:ON / 0:OFF
;-----------------------------------------------------------
IME_GET(WinTitle="A")  {
ControlGet,hwnd,HWND,,,%WinTitle%
if (WinActive(WinTitle)) {
ptrSize := !A_PtrSize ? 4 : A_PtrSize
   VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
   NumPut(cbSize, stGTI,  0, "UInt")   ; DWORD   cbSize;
hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
            ? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
}

   return DllCall("SendMessage"
         , UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
         , UInt, 0x0283  ;Message : WM_IME_CONTROL
         , Int, 0x0005  ;wParam  : IMC_GETOPENSTATUS
         , Int, 0)      ;lParam  : 0
}

;-----------------------------------------------------------
; IMEの状態をセット
;   SetSts          1:ON / 0:OFF
;   WinTitle="A"    対象Window
;   戻り値         0:成功 / 0以外:失敗
;-----------------------------------------------------------
IME_SET(SetSts, WinTitle="A")    {
ControlGet,hwnd,HWND,,,%WinTitle%
if (WinActive(WinTitle)) {
ptrSize := !A_PtrSize ? 4 : A_PtrSize
   VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
   NumPut(cbSize, stGTI,  0, "UInt")   ; DWORD   cbSize;
hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
            ? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
}

   return DllCall("SendMessage"
         , UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
         , UInt, 0x0283  ;Message : WM_IME_CONTROL
         , Int, 0x006   ;wParam  : IMC_SETOPENSTATUS
         , Int, SetSts) ;lParam  : 0 or 1
}

;=============================
; IME 入力モード (どの IMEでも共通っぽい)
;   DEC HEX    BIN
;     0 (0x00  0000 0000) かな    半英数
;     3 (0x03  0000 0011)         半カナ
;     8 (0x08  0000 1000)         全英数
;     9 (0x09  0000 1001)         ひらがな
;    11 (0x0B  0000 1011)         全カタカナ
;    16 (0x10  0001 0000) ローマ字半英数
;    19 (0x13  0001 0011)         半カナ
;    24 (0x18  0001 1000)         全英数
;    25 (0x19  0001 1001)         ひらがな
;    27 (0x1B  0001 1011)         全カタカナ

;  ※ 地域と言語のオプション - [詳細] - 詳細設定
;     - 詳細なテキストサービスのサポートをプログラムのすべてに拡張する
;    が ONになってると値が取れない模様 
;    (Google日本語入力βはここをONにしないと駄目なので値が取れないっぽい)

;-------------------------------------------------------
; IME 入力モード取得
;   WinTitle="A"    対象Window
;   戻り値         入力モード
;--------------------------------------------------------
IME_GetConvMode(WinTitle="A")   {
ControlGet,hwnd,HWND,,,%WinTitle%
if (WinActive(WinTitle)) {
ptrSize := !A_PtrSize ? 4 : A_PtrSize
   VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
   NumPut(cbSize, stGTI,  0, "UInt")   ; DWORD   cbSize;
hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
            ? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
}
   return DllCall("SendMessage"
         , UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
         , UInt, 0x0283  ;Message : WM_IME_CONTROL
         , Int, 0x001   ;wParam  : IMC_GETCONVERSIONMODE
         , Int, 0)      ;lParam  : 0
}

;-------------------------------------------------------
; IME 入力モードセット
;   ConvMode        入力モード
;   WinTitle="A"    対象Window
;   戻り値         0:成功 / 0以外:失敗
;--------------------------------------------------------
IME_SetConvMode(ConvMode,WinTitle="A")   {
ControlGet,hwnd,HWND,,,%WinTitle%
if (WinActive(WinTitle)) {
ptrSize := !A_PtrSize ? 4 : A_PtrSize
   VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
   NumPut(cbSize, stGTI,  0, "UInt")   ; DWORD   cbSize;
hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
            ? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
}
   return DllCall("SendMessage"
         , UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
         , UInt, 0x0283      ;Message : WM_IME_CONTROL
         , Int, 0x002       ;wParam  : IMC_SETCONVERSIONMODE
         , Int, ConvMode)   ;lParam  : CONVERSIONMODE
}

;============================================
; IME 変換モード (ATOKはver.16で調査、バージョンで多少違うかも)

;   MS-IME  0:無変換 / 1:人名/地名                    / 8:一般 /16:話し言葉
;   ATOK系  0:固定 / 1:複合語              / 4:自動 / 8:連文節
;   WXG             / 1:複合語 / 2:無変換 / 4:自動 / 8:連文節
;   SKK系            / 1:ノーマル (他のモードは存在しない?)
;   Googleβ                                          / 8:ノーマル
;------------------------------------------------------------------
; IME 変換モード取得
;   WinTitle="A"    対象Window
;   戻り値 MS-IME  0:無変換 1:人名/地名               8:一般 16:話し言葉
;          ATOK系 0:固定   1:複合語  4:自動 8:連文節
;          WXG4      1:複合語 2:無変換 4:自動 8:連文節
;------------------------------------------------------------------
IME_GetSentenceMode(WinTitle="A")   {
ControlGet,hwnd,HWND,,,%WinTitle%
if (WinActive(WinTitle)) {
ptrSize := !A_PtrSize ? 4 : A_PtrSize
   VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
   NumPut(cbSize, stGTI,  0, "UInt")   ; DWORD   cbSize;
hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
            ? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
}
   return DllCall("SendMessage"
         , UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
         , UInt, 0x0283  ;Message : WM_IME_CONTROL
         , Int, 0x003   ;wParam  : IMC_GETSENTENCEMODE
         , Int, 0)      ;lParam  : 0
}

;----------------------------------------------------------------
; IME 変換モードセット
;   SentenceMode
;       MS-IME 0:無変換 1:人名/地名               8:一般 16:話し言葉
;       ATOK系 0:固定   1:複合語  4:自動 8:連文節
;       WXG         1:複合語 2:無変換 4:自動 8:連文節
;   WinTitle="A"    対象Window
;   戻り値         0:成功 / 0以外:失敗
;-----------------------------------------------------------------
IME_SetSentenceMode(SentenceMode,WinTitle="A")  {
ControlGet,hwnd,HWND,,,%WinTitle%
if (WinActive(WinTitle)) {
ptrSize := !A_PtrSize ? 4 : A_PtrSize
   VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
   NumPut(cbSize, stGTI,  0, "UInt")   ; DWORD   cbSize;
hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
            ? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
}
   return DllCall("SendMessage"
         , UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
         , UInt, 0x0283          ;Message : WM_IME_CONTROL
         , Int, 0x004           ;wParam  : IMC_SETSENTENCEMODE
         , Int, SentenceMode)   ;lParam  : SentenceMode
}


;---------------------------------------------------------------------------
;  IMEの種類を選ぶかもしれない関数

;===========================================
;  IME 文字入力の状態を返す
;  (パクリ元 : http://sites.google.com/site/agkh6mze/scripts#TOC-IME- )
;    標準対応IME : ATOK系 / MS-IME2002 2007 / WXG / SKKIME
;    その他のIMEは 入力窓/変換窓を追加指定することで対応可能
;
;       WinTitle="A"   対象Window
;       ConvCls=""     入力窓のクラス名 (正規表現表記)
;       CandCls=""     候補窓のクラス名 (正規表現表記)
;       戻り値 1 : 文字入力中 or 変換中
;                   2 : 変換候補窓が出ている
;                   0 : その他の状態
;
;   ※ MS-Office系で 入力窓のクラス名 を正しく取得するにはIMEのシームレス表示を
;      OFFにする必要がある
;      オプション-編集と日本語入力-編集中の文字列を文書に挿入モードで入力する
;      のチェックを外す
;================================================
IME_GetConverting(WinTitle="A",ConvCls="",CandCls="") {

   ;IME毎の 入力窓/候補窓Class一覧 ("|" 区切りで適当に足してけばOK)
   ConvCls .= (ConvCls ? "|" : "")                 ;--- 入力窓 ---
           . "ATOK\d+CompStr"                     ; ATOK系
           . "|imejpstcnv\d+"                     ; MS-IME系
           . "|WXGIMEConv"                        ; WXG
           . "|SKKIME\d+\.*\d+UCompStr"           ; SKKIME Unicode
           . "|MSCTFIME Composition"              ; Google日本語入力

   CandCls .= (CandCls ? "|" : "")                 ;--- 候補窓 ---
           . "ATOK\d+Cand"                        ; ATOK系
           . "|imejpstCandList\d+|imejpstcand\d+" ; MS-IME 2002(8.1)XP付属
           . "|mscandui\d+\.candidate"            ; MS Office IME-2007
           . "|WXGIMECand"                        ; WXG
           . "|SKKIME\d+\.*\d+UCand"              ; SKKIME Unicode
  CandGCls := "GoogleJapaneseInputCandidateWindow" ;Google日本語入力

ControlGet,hwnd,HWND,,,%WinTitle%
if (WinActive(WinTitle)) {
ptrSize := !A_PtrSize ? 4 : A_PtrSize
   VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
   NumPut(cbSize, stGTI,  0, "UInt")   ; DWORD   cbSize;
hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
            ? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
}

   WinGet, pid, PID,% "ahk_id " hwnd
   tmm:=A_TitleMatchMode
   SetTitleMatchMode, RegEx
   ret := WinExist("ahk_class " . CandCls . " ahk_pid " pid) ? 2
       :  WinExist("ahk_class " . CandGCls                 ) ? 2
       :  WinExist("ahk_class " . ConvCls . " ahk_pid " pid) ? 1
       :  0
   SetTitleMatchMode, %tmm%
   return ret
}


 エクセルに関してはかつてもっと多くのショートカットキーをAutohotkeyで作っていたのだが、エクセルのAddinであるRelaxtoolsが登場して以来、ほとんどそちらの機能をショートカットキーで呼び出すように変えてしまった。更にエクセルを便利にしたい人は見てみると良いだろう。 

https://software.opensquare.net/relaxtools/



IMEの制御が出来ると色々捗る

 IME.ahkのファイルを紹介したので後回しにしていたIME制御系の便利スクリプトを記載しておく。

IMEをON/OFFするときにはAlt+半角/全角 で切り替えるというのはPCを使い始める時にまず習うことであろう。しかし、このトグルするというのは今IMEがOFFなのかONなのか非常に分かりづらい。タスクバーを見ろよという意見もあるだろうが、それだったら、半角/全角キーを押したら常にIMEはON、無変換キーを押したら常にIMEはOFFというふうに設定したほうが、何も考えずにタイプすれば良いので楽である。

コード9

;半角・全角でIME ON ############
vkF3::IME_SET(1)
vkF4::IME_SET(1)
Return

;無変換でIME OFF ###############
vk1D::IME_SET(0)
Return


エクスプローラーで選択しているファイルのフルパスを取得する。 

 私は普段ファイラはA/SRを使っている。なんでこれを使っているかという理由の一つにファイル名の取得やフルパスの取得が標準機能として搭載されているのが便利なのである。なぜファイル名やフルパスをそんなにコピーするかというと、システム構築のプロジェクトをしている時にはファイルサーバーにおいたファイルを誰かにレビューして欲しいときや情報展開する時にファイルパスをメールに記載する必要があるからだ。

 多くの人はこの作業をエクスプローラーでまずアドレスバーからパスをコピー&ペーストし、続いてファイルをクリックしてF2キーを押してファイル名をコピー&ペーストしている。新人SEの頃からショートカットでこの作業をしていれば社会人生活を通して10人月ぐらいは生産性向上できるのではないか。

 ただ、A/SRで開かずにたまにエクスプローラーで開いている状態の時にファイルのフルパスを取得したいときがある。そんな時にエクスプローラーのアドレスバーからA/SRにファイルパスをコピー&ペーストしてA/SRのショートカットキーでフルパスを取得するというのは、スマートではない。だからエクスプローラーでもファイルのフルパスだけは取得できるようにしている。以下コード10ではCtrl+Shift+fでエクスプローラーで選択したファイルパスを取得できる様になっている。海外のAutohotkey神による作成スクリプトだが、これには1000時間は救われている気がする。

 

コード10

;エクスプローラの時ファイル名取得
#IfWinActive , ahk_class CabinetWClass
^+f::
clipboard := Explorer_GetSelected()
return


Explorer_GetPath(hwnd="")
{
if !(window := Explorer_GetWindow(hwnd))
return ErrorLevel := "ERROR"
if (window="desktop")
return A_Desktop
path := window.LocationURL
path := RegExReplace(path, "ftp://.*@","ftp://")
StringReplace, path, path, file:///
StringReplace, path, path, /, \, All

; thanks to polyethene
Loop
If RegExMatch(path, "i)(?<=%)[\da-f]{1,2}", hex)
StringReplace, path, path, `%%hex%, % Chr("0x" . hex), All
Else Break
return path
}

Explorer_GetAll(hwnd="")
{
return Explorer_Get(hwnd)
}

Explorer_GetSelected(hwnd="")
{
return Explorer_Get(hwnd,true)
}

Explorer_GetWindow(hwnd="")
{
; thanks to jethrow for some pointers here
   WinGet, process, processName, % "ahk_id" hwnd := hwnd? hwnd:WinExist("A")
   WinGetClass class, ahk_id %hwnd%

if (process!="explorer.exe")
return
if (class ~= "(Cabinet|Explore)WClass")
{
for window in ComObjCreate("Shell.Application").Windows
           ; Some window objects do not have the hwnd property and throw an
           ; exception below.
           ; try
           ; if (window.hwnd!="")
           ; foo = window.Name
           ; IfInString, foo, Windows Explorer
           ; {
               ; MsgBox abcde
           if (window.hwnd==hwnd)
               return window
           ; }
}
else if (class ~= "Progman|WorkerW")
return "desktop" ; desktop found
}

Explorer_Get(hwnd="",selection=false)
{
if !(window := Explorer_GetWindow(hwnd))
return ErrorLevel := "ERROR"
if (window="desktop")
{
ControlGet, hwWindow, HWND,, SysListView321, ahk_class Progman
if !hwWindow ; #D mode
ControlGet, hwWindow, HWND,, SysListView321, A
ControlGet, files, List, % ( selection ? "Selected":"") "Col1",,ahk_id %hwWindow%
base := SubStr(A_Desktop,0,1)=="\" ? SubStr(A_Desktop,1,-1) : A_Desktop
Loop, Parse, files, `n, `r
{
path := base "\" A_LoopField
IfExist %path% ; ignore special icons like Computer (at least for now)
ret .= path "`n"
}
}
else
{
if selection
collection := window.document.SelectedItems
else
collection := window.document.Folder.Items
for item in collection
ret .= item.path "`n"
}
return Trim(ret,"`n")
}


ファイラーで開いているローカルファイルをリポジトリで参照する

 これは余り使う人がいないかもしれない。以前担当していたプロジェクトでドキュメントをSVNで管理していた。通常はローカルにチェックアウトして参照しているのだが、ローカルのファイルが古い時にリポジトリのファイルが新しいのか確認するためにリポジトリブラウザを開く必要がある。マウスで右クリックしてリポジトリブラウザを開くを選択していると遅い為、Ctrl+Shift+qでリポジトリブラウザが開くようにしている。途中でCtrl+Shift+fキーでファイルのフルパスを取得しているのがわかるだろう。

 

コード11

;該当のファイルが格納されているフォルダをSVNリポジトリブラウザで開く
^+q::
str = 
Send,^+f
Sleep 30
str ="C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe " /command:repobrowser /path:"%Clipboard%"
Run,%str%

Return

 

ウィンドウの移動。これは便利でした。ありがとうございました。

;無変換とマウスドラッグでウィンドウ移動
;https://yuruaki.blog.fc2.com/blog-entry-92.html
vk1D & LButton::
	CoordMode,Mouse,Screen
	MouseGetPos,sx,sy,mh
	WinGetPos,wx,wy,,,ahk_id %mh%
	while(GetKeyState("LButton","P")){
		MouseGetPos,mx,my
		WinMove,ahk_id %mh%,,wx-(sx-mx),wy-(sy-my)
	}
return

 


Autohotkeyはまだまだ熱い


Autohotkeyの魅力は自分が使っているアプリでここでいっつもマウスを使うなとか毎回同じような事を繰り返し手で実行しているなと思ったら、Autohotkeyで効率化できないか考えてみて、実際に簡単に試せるのが良い。日本ではかつてAutohotkeyを流行らせる人が頑張っていたのだがサイトが閉鎖してしまった。たまには海外のサイトもググって画期的な使い方をしている人がいないかどうかをチェックするもの良いだろう。


AutoHotKeyをつかってRPAを実現してみた。もしよかったらそちらの記事も読んでほしい。
 

www.norick-matsumoto.com

 

2019/5/17追記

文字数が多いいからって検索流入には影響してないみたいだね

orz