std::map形式のデータを簡単に扱えるコンボボックス (CDataComboBox) [WTL]

(2007.06.21)
#pragma once
 
// WAC.com Class Liblary for Visual C++
// Copyright (C) WAC.com Inc. All rights reserved.
//
// This file is a part of the WAC.com Class Liblary.
// The use and distribution terms for this software are covered by the
// Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
// which can be found in the file CPL.TXT at the root of this distribution.
// By using this software in any fashion, you are agreeing to be bound by
// the terms of this license. You must not remove this notice, or
// any other, from this software.
 
// 05.06.23 : 新規作成 (oka)
// 05.11.28 : コードのブラッシュアップ (sha)
// 05.12.13 : _SetComboBoxCurSelFromDataの作成 (sug)
// 05.12.13 : コードのブラッシュアップ (sug)
// 05.12.22 : LoadComboBoxの仕様変更とブラッシュアップ (sug)
// 06.01.04 : コードの整備 (sug)
// 06.02.09 : コードの整備 (sug)
// 06.04.18 : CDataComboBoxHelperに名称変更 (sha)
// 06.04.19 : CDataComboBoxの作成 (sha)
// 06.05.23 : CDataComboBoxHelperの廃止 (sha)
// 06.05.26 : コードの整備 (sha)
// 06.10.18 : コードの整備 (sha)
// 07.04.19 : CDataComboBoxT::Load()の不具合の修正 (sha)
// 07.04.25 : コードの整備 (sha)
// 07.05.08 : WAC1380 : メモ/カテゴリ カテゴリのメニューが表示されないの修正(imatsu)
// 07.06.20 : コードの整備 (sha)
 
#include <map>
#include <vector>
 
 
////////////////////////////////////////////////////////////////////////////////
// CDataComboBoxT
 
template <class TKey, class TVal, class TBase>
class CDataComboBoxT : public TBase
{
protected:
    typedef CDataComboBoxT                        thisClass;
 
public:
    CDataComboBoxT()
    {
    }
    CDataComboBoxT(HWND hWnd) : TBase(hWnd)
    {
    }
    virtual ~CDataComboBoxT()
    {
    }
 
public:
    HRESULT Load(std::map<TKey, TVal>& Vals)
    {
        USES_CONVERSION;
 
        // リストボックスの初期化
        this->ResetContent();
 
        for (std::map<TKey, TVal>::iterator iter = Vals.begin(); iter != Vals.end(); iter++)
        {
#ifdef UNICODE
            int nIndex = (int)::SendMessageA(m_hWnd, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)W2A(iter->second));
#else
            // NOTE: 第一引数に -1 を設定すると文字列を最後尾に追加する
//            int nIndex = this->InsertString(-1, iter->second);
            int nIndex = this->AddString(iter->second);
#endif
            if (nIndex == LB_ERR)
            {
                ATLASSERT(0);
                continue;
            }
            else if (nIndex == LB_ERRSPACE)
            {
                // 文字列を追加する領域の不足
                ATLASSERT(0);
                continue;
            }
 
            this->SetItemDataPtr(nIndex, (LPVOID)&iter->first);
        }
 
        if (this->GetCount() == 0)
        {
            return S_FALSE;
        }
 
        // 最初のアイテムを選択する
        int nCurSel = this->SetCurSel(0);
        if (nCurSel == CB_ERR)
        {
            // 何も行わない。。
            ATLASSERT(0);
        }
 
        return S_OK;
    }
    HRESULT Load(std::map<TKey, TVal>& Vals, std::vector<TKey> Keys)
    {
        USES_CONVERSION;
 
        // リストボックスの初期化
        this->ResetContent();
 
        for (int i = 0 ; i < (int)Keys.size(); i++)
        {
            TKey& Key = Keys[i];
 
            std::map<TKey, TVal>::iterator iter = Vals.find(Key);
            if (iter == Vals.end())
            {
                ATLASSERT(0);
                continue;
            }
 
#ifdef    UNICODE
            int nIndex = (int)::SendMessageA(m_hWnd, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)W2A(iter->second));
#else
            // NOTE: 第一引数に -1 を設定すると文字列を最後尾に追加する
//            int nIndex = this->InsertString(-1, iter->second);
            int nIndex = this->AddString(iter->second);
#endif
            if (nIndex == LB_ERR)
            {
                ATLASSERT(0);
                continue;
            }
            else if (nIndex == LB_ERRSPACE)
            {
                // 文字列を追加する領域の不足
                ATLASSERT(0);
                continue;
            }
 
            this->SetItemDataPtr(nIndex, (LPVOID)&iter->first);
        }
 
        if (this->GetCount() == 0)
        {
            return S_FALSE;
        }
 
        // 最初のアイテムを選択する
        int nCurSel = this->SetCurSel(0);
        if (nCurSel == CB_ERR)
        {
            // 何も行わない。。
            ATLASSERT(0);
        }
 
        return S_OK;
    }
 
public:
    TKey GetCurData(TKey defaultKey)
    {
        int nCurSel = this->GetCurSel();
        if (nCurSel < 0)
        {
            // NOTE: Edit入力の場合は、ここに入ります。
//            ATLASSERT(0);
            return defaultKey;
        }
 
        return this->GetData(nCurSel, defaultKey);
    }
    int SetCurData(TKey Key)
    {
        int nIndex = this->GetIndexFromData(Key);
        if (nIndex == -1)
        {
//            ATLASSERT(0);
            return -1;
        }
 
        return this->SetCurSel(nIndex);
    }
 
public:
    CString GetText(LPCTSTR szDefaultText = _T(""))
    {
        CString strResult;
        UINT nr = __super::GetWindowText(strResult);
        if (!nr)
        {
//            ATLASSERT(0);
            return szDefaultText;
        }
 
        return strResult;
    }
 
public:
#if 0
    int GetCurSel()
    {
        return this->TBase::GetCurSel();
    }
    int SetCurSel(int nSelect)
    {
        return this->TBase::SetCurSel(nSelect);
    }
#endif
    TKey GetData(int nIndex, const TKey& defaultKey)
    {
        TKey* p = (TKey*)this->GetItemDataPtr(nIndex);
        if (p == NULL)
        {
            ATLASSERT(0);
            return defaultKey;
        }
 
        return (*p);
    }
    // NOTE: TKey::operator ==() が定義されていること
    int GetIndexFromData(const TKey& Key)
    {
        int nIndex = -1;
 
        for (int i = 0; i < this->GetCount(); i++)
        {
            TKey* p = (TKey*)this->GetItemDataPtr(i);
            if (*p == Key)
            {
                nIndex = i;
                break;
            }
        }
 
        return nIndex;
    }
};
 
 
////////////////////////////////////////////////////////////////////////////////
// CDataComboBox
 
template <class TKey, class TVal>
class CDataComboBox : public CDataComboBoxT<TKey, TVal, CComboBox>
{
protected:
    typedef CDataComboBoxT                        thisClass;
 
public:
    CDataComboBox()
    {
    }
    CDataComboBox(HWND hWnd) : CDataComboBoxT<TKey, TVal, CComboBox>(hWnd)
    {
    }
};
一覧に戻る
© 2003 WAC.com All Right Reserved.