オートコンプリート機能を付ける[OLE]

 前は簡易編として逃げていたオートコンプリート機能です。今回のは任意の文字列をオートコンプリートさせることができます。この機能の実現のためにOLE(COM)の技術がいります。今まではCOMと言っても、APIでインスタンスを作成しそのポインタでメソッドを呼び出すくらいでしたが、今回は自分でCOM仕様のクラスを作成しなければいけません。では順を追って説明します。

 簡単な手順はこのドキュメントに書いてありますので参照してください。

◆IEnumStringインターフェイスの実装

 これが冒頭で書いたCOM仕様のクラスの作成です。基本的には目的のインターフェイスを継承したクラスを作成すれば良いだけです。ソースが長いのでコードはサンプルプロジェクトまたはこれを参照してください。ここにはヘッダ宣言だけ掲載します。

class CEnumString : public IEnumString
{
public:
    CEnumString(LPUNKNOWN, ULONG, LPOLESTR*, IMalloc*);
    ~CEnumString(void);

    // IUnknownインターフェイスのメソッド
    STDMETHODIMP         QueryInterface(REFIID iid, LPVOID* ppInterface);
    STDMETHODIMP_(ULONG) AddRef(void);
    STDMETHODIMP_(ULONG) Release(void);

    // IEnumStringインターフェイスのメソッド
    STDMETHODIMP         Next(ULONG cstr, LPOLESTR *rgelt, ULONG *pcstr);
    STDMETHODIMP         Skip(ULONG celt);
    STDMETHODIMP         Reset(void);
    STDMETHODIMP         Clone(IEnumString **ppenum);

    // 変数
private:
    ULONG           m_cRef;     // 参照カウント
    LPUNKNOWN       m_pUnkRef;  // 参照カウントを増やすIUnknownのポインタ
    ULONG           m_iCur;     // 現在のリスト位置
    ULONG           m_cstr;     // クラス内の文字列数
    LPOLESTR        *m_prgstr;  // 文字列のコピー
    IMalloc         *m_pmem;    // IMallocインターフェイスのポインタ
};

これを定義した後、CEnumStringの作成をします。

// IMallocインターフェイスのポインタ取得
if (SHGetMalloc(&pMalloc) == E_FAIL)
    return FALSE;

// オートコンプリートで使う文字列リスト
WCHAR* lpstr[] = {
    L"CL Windows",
    L"Runan",
    L"Akatuki No Youhei",
    L"Mercenary of Dawn",
    L"Free Soft",
    L"Free Market",
    L"Fryday",
    L"France",
    L"Friend",
    L"Float",
    L"Virus"
};

pEnumStr = new CEnumString(NULL, sizeof(lpstr)/sizeof(int), lpstr, pMalloc);

IAutoCompleteインターフェイスの作成

 このステップはAPIを呼び出してインターフェイスを作成するだけです。このステップの前にOLEを初期化する必要があります。作成部分だけ掲載すると..

// IAutoCompleteインターフェイスを作成
if (CoCreateInstance(CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER,
        IID_IAutoComplete, (void**)&pAutoComp) != S_OK)
{
    MessageBox(hWnd, "Fail : CoCreateInstance", NULL, MB_OK);
    return;
}

◆IAutoCompleteとエディットボックスのハンドルを結びつける

 上のステップで取得したIAutoComplete*のInitメソッドを呼び出します。このときに最初のステップで作ったCEnumStringのポインタが必要になります。

// エディットボックスを対象にする
if (pAutoComp->Init(GetDlgItem(hWnd, IDC_EDIT1), pEnumStr, NULL, NULL) != S_OK)
{
    MessageBox(hWnd, "Fail : IAutoComplete->Init", NULL, MB_OK);
    return;
}

◆設定を変更する

 標準では「ファイル名を指定して実行」のような動作になっています。
↓こんなの

これを↓こんなリストモード(IEのアドレスバーみたいなやつ)

にするには、QueryInterfaceを呼び出し、IAutoComplete2インターフェイスへのポインタを取得してから、そのインターフェイスのSetOptionsメソッドを呼び出します。指定できる定数はSetOptionsのドキュメントを参照してください。

/*
    QueryInterfaceメソッドで、
    IAutoComplete2インターフェイスのポインタを取得し
    そのSetOptionsメソッドを呼び出す

    「ファイル名を指定して実行」と同じ動作にしたいならここをコメントアウトする
*/
    IAutoComplete2* pAuto2 = NULL;
    if (SUCCEEDED(pAutoComp->QueryInterface(IID_IAutoComplete2, (void**)&pAuto2))){
        pAuto2->SetOptions(ACO_AUTOSUGGEST);
        pAuto2->Release();
    }

 

 以上で完了です。

サンプルプロジェクトのダウンロード

やっと他ではないようなtipsが掲載できた気がします。これからもこの調子でがんばります。


記事の無断転載は禁止です。 Copyright 1999-2001 Runan. All Rights Reserved.