LoginSignup
3
3

More than 5 years have passed since last update.

条件後入れでウィンドウハンドルを取得できる「WindowExplorerクラス」をつくった

Last updated at Posted at 2015-07-31

作成動機

  • ある条件を満たすウィンドウのハンドル(HWND)を取得したい
  • FindWindowでいいじゃん!
  • ターゲットとなるWindowが複数個あったらダメ
  • EnumWindowがあるじゃん!
  • コールバックEnumWindowsProcが融通きかない!条件かわると使いまわせない!
  • じゃあ内部でEnumWindowしつつ、検索条件をstd::<function>で受け取るクラス作るわ

という経緯です。

使いかた

タイトルが”hello”をさがす
const auto title_is_hello = [](HWND hwnd) -> bool {
    TCHAR buffer[MAX_PATH] = {0};
    ::GetWindowText( hwnd,buffer,MAX_PATH );
    return _tcscmp(_T("hello"), buffer) == 0;
};

const HWND hwnd = WindowExplorer::Search(title_is_hello);

クラス名が”hoge”で子ウィンドウのクラス名が”fuga”
const auto class_is_hoge = [](HWND hwnd) -> bool {
        TCHAR buffer[MAX_PATH] = {0};
        ::GetClassName( hwnd,buffer,MAX_PATH );
        return _tcscmp(_T("hoge"), buffer) == 0;
};

const auto class_is_fuga = [](HWND hwnd) -> HWND {
    return ::FindWindowEx(hwnd, nullptr, _T("fuga"), nullptr);
};
const HWND hwnd = WindowExplorer::Search(class_is_hoge, class_is_fuga);

実装コード

#include <functional>
typedef std::function<bool(HWND)> IsMatchedWindow;
typedef std::function<HWND(HWND)> GetMatchedWindow;

class WindowExplorer
{
public:
    static HWND Search(IsMatchedWindow _condition, GetMatchedWindow _getter = nullptr)
    {
        WindowCondition Condition(_condition, _getter);
        ::EnumWindows( EnumWindowsProc,  (LPARAM)&Condition );
        return Condition.GetHandle();
    }

private:

    class WindowCondition
    {
    private:
        HWND hFoundWnd;
        IsMatchedWindow IsMatchedWindow_;
        GetMatchedWindow GetMatchedWindow_;

    public:
        WindowCondition(IsMatchedWindow cond, GetMatchedWindow getter=nullptr)
            : IsMatchedWindow_(cond)
            , GetMatchedWindow_(getter)
            , hFoundWnd(nullptr)
        {}

        inline HWND GetHandle()const { return hFoundWnd; }
        bool found(HWND hwnd)
        {
            if ( IsMatchedWindow_(hwnd))
            {
                hFoundWnd = ( GetMatchedWindow_ )? GetMatchedWindow_(hwnd) : hwnd;
                return hFoundWnd != nullptr;
            }
            return false;
        }
    };

    static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam )
    {
        WindowCondition* condition = reinterpret_cast<WindowCondition*>(lParam);

        if ( !condition )
            return FALSE;

        if ( condition->found(hwnd) )
            return FALSE;

        return TRUE;
    }
};

C++11の、ラムダ式とstd::functionのおかげで、関数オブジェクトをカジュアルに使えるようになりましたね。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3