2009年9月30日水曜日

アクティブなウィンドウのハンドルからファイルパス取得

 以前ちょっと話題に出した「Manic Time」が面白かったため、似たような機能を作ってみたい! ってことでちょちょいと調べてみた。


●アクティブなウィンドウのタイトルを取得する
 GetForegroundWindowって便利な関数があるのでそれで一発。ウィンドウハンドルが得られるからあとはGetWindowTextするだけ。簡単。

GetForegroundWindow 関数
http://msdn.microsoft.com/ja-jp/library/cc364732.aspx

GetWindowText 関数
http://msdn.microsoft.com/ja-jp/library/cc364815.aspx



●ウィンドウハンドルからファイルパス取得
 「Manic Time」にはプログラム別に色分けして表示する機能があるので、プログラムでユニークな情報が必要そう。「Manic Time」ではどうしているのか知らないけれど、ファイルパスでどうにかできそうなのでファイル名を取得する。ウィンドウハンドルだけからファイルパスを直接取得する関数がないので、いくらか段階を踏む必要がある。

GetWindowThreadProcessIdでプロセスIDを取得

OpenProcessでプロセスハンドルを取得

EnumProcessModulesでモジュールハンドルを取得

GetModuleFileNameExでファイルパスを取得

 といった流れ。GetModuleFileNameExでプロセスとモジュールのハンドルが必要になるので適当にデータを取ってくる。作業。

GetWindowThreadProcessId 関数
http://msdn.microsoft.com/ja-jp/library/cc364779.aspx

OpenProcess 関数
http://msdn.microsoft.com/ja-jp/library/cc429278.aspx

EnumProcessModules 関数
http://msdn.microsoft.com/ja-jp/library/cc429387.aspx

GetModuleFileNameEx 関数
http://msdn.microsoft.com/ja-jp/library/cc429403.aspx


●サンプル

#include <windows.h>
#include <cstdio>
 
#include <psapi.h>
#pragma comment(lib, "psapi.lib")
 
 
bool getWindowFileName( HWND hWnd, LPSTR lpFileName, DWORD nSize )
{
  DWORD processID;
  GetWindowThreadProcessId( hWnd, &processID );
  HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
  bool ret = false;
  if ( hProcess )
  {
    HMODULE hModule;
    DWORD cbReturned;
    if ( EnumProcessModules( hProcess, &hModule, sizeof(hModule), &cbReturned ) )
    {
      ret = 0 != GetModuleFileNameEx( hProcess, hModule, lpFileName, nSize );
    }
    CloseHandle( hProcess );
  }
 
  return ret;
}
 
int main()
{
  for (;;)
  {
    HWND hWnd = GetForegroundWindow();
 
    TCHAR title[ 1024 ];
    ZeroMemory( title, sizeof(title) );
    GetWindowText( hWnd, title, sizeof(title)/sizeof(*title) );
 
    TCHAR fileName[ 1024 ];
    ZeroMemory( fileName, sizeof(fileName) );
    getWindowFileName( hWnd, fileName, sizeof(fileName)/sizeof(*fileName) );
 
    std::printf("%s [%s]\n", title, fileName );
    Sleep( 1000 );
  }
}



●ほか
 あとは収集したデータをグラフィカルに表示すればOKといったところだろうけど、そこが一番面倒くさい。

 以下のサイトを参考にしました。感謝。
Win32 API でアプリケーションを列挙する方法
http://support.microsoft.com/default.aspx?scid=kb;ja;175030

ファイル名を取得するには
http://hpcgi1.nifty.com/MADIA/Vcbbs/wwwlng.cgi?print+200504/05040053.txt

 
 
/** 11-06-05 */
 hProcessを閉じ忘れていたのを修正

0 件のコメント: