WTLでリストビューをオーナードローする

test100_01.gif
ATL/WTLアプリケーションウイザードでプロジェクトを作成する際に、プロジェクトウイザードの3枚目のユーザーインターフェース機能の設定画面でビューウインドウの形式として「リストビュー」を選択する。

生成したソースコードの中でMainFrm.hのメッセージマップの末尾にかなりトリッキーな方法だがWM_DRAWITEMメッセージをビューで処理するためのコードを追加する。
	BEGIN_MSG_MAP(CMainFrame)
(...省略...)
		{
			if(uMsg == WM_DRAWITEM && ((DRAWITEMSTRUCT*)lParam)->hwndItem == m_view.m_hWnd)
				return	m_view.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, dwMsgMapID);
		}
	END_MSG_MAP()

OnCreate内にあるビュークラスの生成部分でウインドウスタイルとしてLVS_OWNERDRAWFIXEDを追加する。
		m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, LVS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | LVS_REPORT | LVS_SHOWSELALWAYS, WS_EX_CLIENTEDGE);

さらにOnCreate内にテスト用のカラムとアイテムを追加するコードを入れる。
		m_view.InsertColumn(0, _T("カラム1"), LVCFMT_LEFT, 190, -1);
		m_view.InsertColumn(0, _T("カラム2"), LVCFMT_LEFT, 190, -1);
		m_view.AddItem(0,0,_T("アイテム1"));
		m_view.AddItem(0,1,_T("アイテム1あああああああああああああああああ"));
		m_view.AddItem(1,0,_T("アイテム2"));
		m_view.AddItem(1,1,_T("アイテム2あああああああああああああああああ"));

次にビュークラスの先頭にインクルード宣言を追加する。
#include "atlstr.h"

同じくビュークラス内のメッセージマップにWM_DRAWITEMメッセージの処理用ハンドラーを追加する。
	BEGIN_MSG_MAP(CTest100View)
		MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)
	END_MSG_MAP()

最後にビュークラス内にオーナードロー用のコードを追加する。ここではイメージリストなどの複雑な処理は一切省き、単にカラム内の文字列を表示するだけの処理にしている。
	LRESULT OnDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
	{
		LPDRAWITEMSTRUCT	pDrawItem;

		pDrawItem = (LPDRAWITEMSTRUCT)lParam;

		int		i;
		int		nSize;
		BSTR	bstrText;
		BOOL	ret;
		RECT	rect;
		HBRUSH		hBrush;
		COLORREF	clrOldBack;
		COLORREF	clrOldText;

		nSize = GetHeader().GetItemCount();
		for(i = 0; i < nSize; i++)
		{
			//描画文字列の取得(BSTRとして取得)
			bstrText = NULL;
			ret = GetItemText(pDrawItem->itemID,i,bstrText);
			if(ret == FALSE)
				continue;

			//描画領域を取得
			GetHeader().GetItemRect(i,&rect);
			rect.top	= pDrawItem->rcItem.top;
			rect.bottom	= pDrawItem->rcItem.bottom;

			//アイテム選択時処理
			if(pDrawItem->itemState & ODS_SELECTED)
			{
				clrOldBack = ::SetBkColor(pDrawItem->hDC,::GetSysColor(COLOR_HIGHLIGHT));
				clrOldText = ::SetTextColor(pDrawItem->hDC,::GetSysColor(COLOR_HIGHLIGHTTEXT));
				hBrush = ::GetSysColorBrush(COLOR_HIGHLIGHT);
				::FillRect(pDrawItem->hDC,&rect,hBrush);
			}

			//文字の描画
			::DrawText(pDrawItem->hDC,(CAtlString)(WCHAR*)bstrText,-1,&rect,DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS);

			//BSTRの解放
			::SysFreeString(bstrText);


			//アイテム選択時処理
			if(pDrawItem->itemState & ODS_SELECTED)
			{
				::SetBkColor(pDrawItem->hDC,clrOldBack);
				::SetTextColor(pDrawItem->hDC,clrOldText);
				::DeleteObject(hBrush);
			}
		}

		return	0;
	}

test100_02.gif
これで実行すると見た目には普通のリストビューが表示される。しかし内部的にはオーナードローにて描画されている。

プロジェクトファイルをダウンロード


カテゴリー「ウインドウ操作」 のエントリー