ホーム ATL/WTL
ソートリストビュー
ドキュメント種別 ATL/WTL に関する文書
最終更新日 2005/07/18
PR
 ソートリストビューは、ソート機能付きのリストビューコントロールです。 WTLはソートリストビューを作成するためにCSortListViewCtrlというクラスを用意しています。

CSortListViewCtrlクラスはCListViewCtrlクラスから派生しています。 以下に示すのは、CSortListViewCtrlクラスを使用する例です。



// stdafx.h内
#include <atlbase.h>
#include <atlapp.h>
extern CAppModule _Module;
#include <atlwin.h>

#include <atlcrack.h>
#include <atlmisc.h>
#include <atlctrls.h>
#include <atlctrlx.h>  // CSortListViewCtrlクラスを使用するため
			

// maindlg.h内
class CMainDlg : public CDialogImpl<CMainDlg>
{
public:
    enum { IDD = IDD_MAINDLG };

    CSortListViewCtrl m_list_dir;     // ソートリストビュー

    // メッセージマップ
    BEGIN_MSG_MAP_EX(CMainDlg)
        MSG_WM_INITDIALOG(OnInitDialog)
        COMMAND_ID_HANDLER_EX(IDOK, OnOK)
        COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel)
    END_MSG_MAP()

    LRESULT OnInitDialog(HWND hWnd, LPARAM lParam){
        // スクリーンの中央に配置
        CenterWindow();

        // 大きいアイコン設定
        HICON hIcon = AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR,
            ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));
        SetIcon(hIcon, TRUE);
        
        // 小さいアイコン設定
        HICON hIconSmall = AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR,
            ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));
        SetIcon(hIconSmall, FALSE);

        // コントロール設定
        m_list_dir.SubclassWindow(GetDlgItem(IDC_LIST_DIR));

        // ソートリストビューにカラム設定
        CRect rcList;
        m_list_dir.GetWindowRect(rcList);
        int nScrollWidth = GetSystemMetrics(SM_CXVSCROLL);
        int n3DEdge = GetSystemMetrics(SM_CXEDGE);
        m_list_dir.InsertColumn(0, _T("名前"), LVCFMT_LEFT, 190, -1);
        m_list_dir.InsertColumn(1, _T("名前の長さ"), LVCFMT_LEFT,
            rcList.Width() - 190 - nScrollWidth - n3DEdge * 2, -1);

        // ソートタイプ設定
        m_list_dir.SetColumnSortType(0, LVCOLSORT_TEXT);
        m_list_dir.SetColumnSortType(1, LVCOLSORT_LONG);
        
        // ソートリストビューにアイテム追加
        CFindFile find;
        if(find.FindFile()){
            do{
                if(!find.IsDots()){
                    int nIndex = m_list_dir.GetItemCount();
                    m_list_dir.AddItem(nIndex, 0, find.GetFileName());
                    CString strLength;
                    strLength.Format(_T("%d"), find.GetFileName().GetLength());
                    m_list_dir.AddItem(nIndex, 1, strLength);
                }
            }while(find.FindNextFile());
        }

        return TRUE;
    }

    void OnOK(UINT uNotifyCode, int nID, HWND hWndCtl){
        EndDialog(nID);
    }

    void OnCancel(UINT uNotifyCode, int nID, HWND hWndCtl){
        EndDialog(nID);
    }
};
			

// Control.cpp内
#include "stdafx.h"

#include "resource.h"

#include "maindlg.h"

CAppModule _Module;

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR lpCmdLine, int nCmdShow)
{
    HRESULT hRes = ::CoInitialize(NULL);
    ATLASSERT(SUCCEEDED(hRes));

    ::DefWindowProc(NULL, 0, 0, 0L);

    AtlInitCommonControls(ICC_COOL_CLASSES | ICC_WIN95_CLASSES);

    hRes = _Module.Init(NULL, hInstance);
    ATLASSERT(SUCCEEDED(hRes));

    int nRet = 0;
    // BLOCK: アプリケーション実行
    {
        CMainDlg dlgMain;
        nRet = dlgMain.DoModal();
    }

    _Module.Term();
    ::CoUninitialize();

    return nRet;
}
			

 まず、リソースを作成します。ダイアログにリストビューコントロールを配置し、 リソースIDを次のように指定します。 なお、リストビューコントロールの[スタイル]ではデフォルトに加え[表示]で[レポート]を選択し、 [選択を常に表示]にチェックを入れます。

コントロール名 リソースID
リストビュー IDC_LIST_DIR

 CMainDlgクラスでは、まず、 CSortListViewCtrlクラスのインスタンスをメンバ変数として宣言します。 これを使うためには、WM_INITDIALOGメッセージハンドラでサブクラス化する必要があります。

 次に、WM_INITDIALOGメッセージハンドラでソートリストビューにカラムを追加し、 それぞれのカラムにソートタイプを設定します。 ソートリストビューでは以下のソートタイプを設定することができます。

ソートタイプ 意味 オーバーライド可能な比較関数
LVCOLSORT_NONE ソートしない -
LVCOLSORT_TEXT テキスト値としてソート(デフォルト) LVCompareText()
LVCOLSORT_TEXTNOCASE 大文字と小文字を区別しないテキスト値としてソート LVCompareTextNoCase()
LVCOLSORT_LONG long値としてソート LVCompareLong()
LVCOLSORT_DOUBLE double値としてソート LVCompareDouble()
LVCOLSORT_DECIMAL 小数値としてソート LVCompareDecimal()
LVCOLSORT_DATETIME 日時としてソート LVCompareDouble()
LVCOLSORT_DATE 日付としてソート LVCompareDouble()
LVCOLSORT_TIME 時間としてソート LVCompareDouble()
LVCOLSORT_CUSTOM 独自のデータとしてソート LVCompareCustom()

カラムにソートタイプを設定しなければ、 デフォルトでLVCOLSORT_TEXTが設定されます。

ソートリストビューでは、カラムをクリックすると比較関数が呼び出されます。 比較関数はオーバーライド可能で、ユーザ独自の比較コードを書くことができます。 なお、ソートタイプにLVCOLSORT_CUSTOMを設定した場合は、 比較関数であるLVCompareCustom()の内部で CompareItemsCustom()が呼び出されるのでCompareItemsCustom() をオーバーライドします。

 最後に、ソートリストビューにカレントディレクトリ内のフォルダとファイルをアイテムとして追加します。

 このようにソートリストビューを使用すると、 ソートのためのコードを書くことなく、昇順/降順ソート機能を持ったリストビューを作成することができます。

 ところで、上の例ではソートリストビューを作成するために、 ダイアログ上にコントロールリソースを配置してサブクラス化しましたが、 Create()を使って作成することもできます。

m_list_dir.Create(m_hWnd, CRect(0, 0, 200, 100), NULL, 0, 0, IDC_LIST_DIR);
			

サブクラス化によって作成した場合はリソースのプロパティによってスタイル([レポート]や[選択を常に表示])を設定しましたが、 Create()を使って作成した場合は、スタイルを第4引数(ウィンドウスタイル)、 第5引数(拡張ウィンドウスタイル)によって設定します。 これらの引数に 0 を指定した場合は、デフォルトのウィンドウ特性としてCSortListViewCtrlTraitsクラスが使用されます。 CSortListViewCtrlTraitsクラスはatlctrlx.hヘッダ内で次のように宣言されています。

typedef ATL::CWinTraits<WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | 
    LVS_REPORT | LVS_SHOWSELALWAYS , WS_EX_CLIENTEDGE>   CSortListViewCtrlTraits;
			

CSortListViewCtrlクラスは次のように定義されています。

// atlctrlx.h内
// CSortListViewCtrlクラスの基底クラス
template <class T, class TBase = CListViewCtrl,
    class TWinTraits = CSortListViewCtrlTraits>
class ATL_NO_VTABLE CSortListViewCtrlImpl : 
    public ATL::CWindowImpl<T, TBase, TWinTraits>, public CSortListViewImpl<T>
{
    ...
    ...
};

class CSortListViewCtrl : public CSortListViewCtrlImpl<CSortListViewCtrl>
{
public:
    DECLARE_WND_SUPERCLASS(_T("WTL_SortListViewCtrl"), GetWndClassName())
};
			

CSortListViewCtrlImplクラスの第3テンプレート引数に独自のウィンドウ特性を指定することで、 ソートリストビューのウィンドウスタイルを変更することが出来ます。