ウィンドウがあればアクティブに、無ければ新規に開くツール


bluewind というコマンドラインランチャと DDwin という EPWING 辞書ツールを愛用しているのだが、bluewind はすでに開いているかどうかお構いなしに起動してくれるので、ふと気がつくとタスクバーに DDwin が6つくらい並んでいたりする。
指定したプログラムがすでに開かれていればアクティブに、開いていなければ新規に開くことが出来れば嬉しいのだが、bluewind にはそういう設定項目はなく、ちょこっと探した範囲ではそういうものを見つけることも出来なかった。誰か作ってそうな気もするんだけど。


というわけで、まあそろそろ WINAPI の勉強もしといた方がいいかな、というのを兼ねて activatewin というのを作ってみた。
リンク先(github)の Release の下にビルド済みバイナリが転がっている。


http://github.com/shuyo/cpp/tree/6b7de731a59f1b44f83ca631fbe5a0bf39e762a1/activatewin


activatewin.exe の第1引数にウィンドウクラス名、第2引数にプログラムのパスを与えれば、指定のウィンドウクラスが存在していればアクティブに、存在していなければプログラムを新規プロセスで起動する、という単純なツールだが、DDwin が複数起動しなくなってとっても幸せ。
ウィンドウクラス名を指定しないといけないということで、SPY++ とかその手のツールでウィンドウクラスを調べなければいけないのが難だが、まあウィンドウタイトルの部分一致とか言い出すと途端にめんどくさくなるのでパス。
ちなみに DDwin のウィンドウクラスは TDDwin だった。


コードはたったこれだけ。8K 未満の実行バイナリなんて X68000 でプログラム書いてた頃以来やわー(ん? DLL?)。

#define UNICODE
#include <Windows.h>

int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow) {

  int    argc;
  LPTSTR *argv;
  argv = CommandLineToArgvW(GetCommandLine(), &argc);

  BOOL result = 0;

  if (argc > 1) {
    HWND wnd = FindWindow(argv[1], NULL);
    HWND app = GetWindow(wnd, GW_OWNER);  // これをしないと一度最小化から戻った後、最小化ボタンが効かなくなる
    if (IsIconic(app)) ShowWindow(app, SW_SHOWNORMAL);  // 最小化されていれば戻す
    result = SetForegroundWindow(app);
  }
  if (result == 0 && argc > 2) {
    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    ZeroMemory(&si,sizeof(si));
    si.cb=sizeof(si);
    CreateProcess(NULL, argv[2], NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
    CloseHandle(pi.hThread);
  }

  LocalFree(argv);
  return 0;
}


しかし、使ってるツールがどれもこれも古いな〜って?
環境をバージョンアップできない人間なもんで。いやはや。


実は秀丸で F12 を叩くと ant が起動する設定になってるとか、Visual Studio で cpp ファイルをダブルクリックすると秀丸が立ち上がる設定になってるなんて、ちょっと人には言われへんなあ。