IShell クラスのラッパー

主に ISHELL_CreateInstance をラップするための存在だったりするのですが。
で、RVCT3.0 は例外が使える(らしい)ので ISHELL_CreateInstance に失敗したら例外を投げてやることにします。
また、BREW API 用の interusive なスマートポインタ(brew_ptr)を自作したおかげで IBase にキャストして返すことができるし、参照カウンタ方式のスマートポインタと違って管理用のメモリをアロケートする必要もないので、かなりスマートな感じに生成することができます。

class shell
{
private:
    brew_ptr<IShell> p_;

public:
    // implicit
    shell(IShell* p) : p_(p) { }
    IShell* get() const { return p_.get(); }

    brew_ptr<IBase> create(AEECLSID clsid) const
    {
        brew_ptr<IBase> p;
        int result = ISHELL_CreateInstance(p_.get(), clsid, reinterpret_cast<void**>(p.address()));
        if (result != SUCCESS)
        {
            throw brew_exception(result);
        }
        return p;
    }

    void close_applet() const
    {
        ISHELL_CloseApplet(p_.get(), FALSE);
    }
};
shell sh(pShell);
brew_ptr<IDisplay> disp(static_pointer_cast<IDisplay>(sh.create(AEECLSID_DISPLAY)));

あとはまあ、ISHELL_SetTimerEx のラッパーなんかも作っておくと幸せになれるかもしれません。

class callback
{
public:
    callback()
    {
        MEMSET(&cb_, 0, sizeof(AEECallback));
    }
    callback(PFNNOTIFY pfn, void* user)
    {
        MEMSET(&cb_, 0, sizeof(AEECallback));
        reset(pfn, user);
    }
    ~callback()
    {
        cancel();
    }

    void reset(PFNNOTIFY pfn, void* user)
    {
        cancel();
        CALLBACK_Init(&cb_, pfn, user);
    }
    void cancel()
    {
        CALLBACK_Cancel(&cb_);
    }

    AEECallback* get() { return &cb_; }

private:
    AEECallback         cb_;
};

class shell
{
    ...

    void set_timer(callback& cb, int ms) const
    {
        ISHELL_SetTimerEx(p_.get(), ms, cb.get());
    }
};