⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sortlistviewctrlex.hpp

📁 j2me is based on j2mepolish, client & server for mobile application.
💻 HPP
字号:

//         Copyright E骾n O'Callaghan 2008 - 2008.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#ifndef SORTLISTVIEWCTRLEX_HPP_INCLUDED
#define SORTLISTVIEWCTRLEX_HPP_INCLUDED

#include <boost/ptr_container/ptr_map.hpp>

#include "SettingsIni.hpp"
#include "UpdateLock.hpp"

#define LVS_EX_DOUBLEBUFFER     0x00010000

#define ID_LVM_AUTOSORT 0

namespace WTLx
{

template <class TBase, typename adapterType=void*>
class SortListViewCtrlEx : 
	public WTL::CSortListViewCtrlImpl<SortListViewCtrlEx<TBase, adapterType> >,
	public WTLx::update_lockable<SortListViewCtrlEx<TBase, adapterType> >
{
public:
	typedef SortListViewCtrlEx<TBase, adapterType> thisClass;
	typedef CSortListViewCtrlImpl<thisClass> parentClass;

	class SortHeaderCtrl : public CWindowImpl<SortHeaderCtrl, WTL::CHeaderCtrl>
	{
	public:
		enum { COL_MENU_NAMES_ID_START = 123, COL_MAX_NAMES = 256};

		SortHeaderCtrl(thisClass& listView) :
			listView_(listView)
		{}
			
		DECLARE_WND_SUPERCLASS(NULL, parentClass::GetWndClassName())

		BEGIN_MSG_MAP(SortHeaderCtrl)
			REFLECTED_NOTIFY_CODE_HANDLER(NM_RCLICK, OnRClick)
			COMMAND_RANGE_HANDLER(COL_MENU_NAMES_ID_START, 
				COL_MENU_NAMES_ID_START+COL_MAX_NAMES, OnMenuNames)

			DEFAULT_REFLECTION_HANDLER()
		END_MSG_MAP()
		
		LRESULT OnRClick(int i, LPNMHDR pnmh, BOOL&)
		{
			WTL::CPoint point;
			GetCursorPos(&point);
			menu_.TrackPopupMenu(0, point.x, point.y, m_hWnd);

			return 0;
		}

		LRESULT OnMenuNames(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
		{		
			ATLASSERT(wID-COL_MENU_NAMES_ID_START <= GetItemCount());

			bool visible = listView_.OnNameChecked(wID-COL_MENU_NAMES_ID_START);

			return 0;
		}

		WTL::CMenu& Menu()
		{
			return menu_;
		}
		
	private:
		WTL::CMenu menu_;
		thisClass& listView_;
	};

	struct ColumnAdapter
	{
		virtual int compare(adapterType& l, adapterType& r) = 0;
		virtual std::wstring print(adapterType& t) = 0;
	};

public:	
	SortListViewCtrlEx() :
		header_(*this),
		auto_sort_(false),
		descending_(false),
		sort_col_(-1)
	{}

	BEGIN_MSG_MAP_EX(thisClass)
		COMMAND_ID_HANDLER(ID_LVM_AUTOSORT, OnAutoSort)
		
		REFLECTED_NOTIFY_CODE_HANDLER(NM_RCLICK, OnRClick)

		DEFAULT_REFLECTION_HANDLER()
		CHAIN_MSG_MAP(parentClass)
	END_MSG_MAP()
	
	HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
			DWORD dwStyle = 0, DWORD dwExStyle = 0,
			ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
	{
		HWND hwnd = parentClass::Create(hWndParent, 
			(RECT &)rect.m_lpRect, szWindowName, dwStyle, dwExStyle, (UINT)MenuOrID.m_hMenu, lpCreateParam);

		return hwnd;
	}
	
	bool SubclassWindow(HWND hwnd)
	{
		if(!parentClass::SubclassWindow(hwnd))
			return false;			

		InitialSetup();
		
		return true;
	}

	void InitialSetup(WTL::CMenuHandle menu=WTL::CMenuHandle())
	{
		SetExtendedListViewStyle(LVS_EX_HEADERDRAGDROP|LVS_EX_DOUBLEBUFFER);
		SetSortListViewExtendedStyle(SORTLV_USESHELLBITMAPS,SORTLV_USESHELLBITMAPS);

		MENUITEMINFO minfo = {sizeof(MENUITEMINFO)};
		
		if (!menu)
		{
		//	menu_.CreatePopupMenu();
		}
		else
		{		
			menu_.Attach(menu.GetSubMenu(0));

		//	minfo.fMask = MIIM_SUBMENU;
		//	minfo.fType = MFT_SEPARATOR;
			
		//	menu_.InsertMenuItem(menu_.GetMenuItemCount(), true, &minfo);		
		}

		//minfo.fMask = MIIM_STRING|MIIM_ID|MIIM_FTYPE|MIIM_STATE;
		//minfo.fType = MFT_STRING;
		//minfo.fState = auto_sort_ ? MFS_CHECKED : MFS_UNCHECKED;
		//minfo.wID = ID_LVM_AUTOSORT;
		
		//std::wstring autoarrange = aux::app.res_wstr(IDS_AUTOSORT);
		//minfo.dwTypeData = (LPWSTR)autoarrange.c_str();
		
		//menu_.InsertMenuItem(menu_.GetMenuItemCount(), true, &minfo);

		header_.SubclassWindow(this->GetHeader());
		header_.ModifyStyle(0, HDS_DRAGDROP|HDS_FULLDRAG);
		if (header_.Menu().IsNull()) 
			header_.Menu().CreatePopupMenu();
	}

	int AddColumn(LPCTSTR strItem, int nItem, bool visible, int width=-1)
	{
		return AddColumn(strItem, nItem, -1,
			LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM,
			LVCFMT_LEFT, visible, width);
	}

	int AddColumn(LPCTSTR strItem, int nItem, int nSubItem = -1,
			int nMask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM,
			int nFmt = LVCFMT_LEFT, bool visible=true, int width=-1)
	{

		int i = parentClass::AddColumn(strItem, nItem, nSubItem, nMask, nFmt);

		if (i == -1) return i;

		if (width != -1) SetColumnWidth(i, width);

		if (header_.Menu().IsNull()) 
			header_.Menu().CreatePopupMenu();

		WTL::CMenuHandle menu = header_.Menu();

		MENUITEMINFO minfo = {sizeof(MENUITEMINFO)};
		minfo.fMask = MIIM_STRING|MIIM_ID|MIIM_FTYPE|MIIM_STATE;
		minfo.fType = MFT_STRING;
		minfo.dwTypeData = (LPTSTR)strItem;
		minfo.wID = SortHeaderCtrl::COL_MENU_NAMES_ID_START+i;

		if (visible)
			minfo.fState = MFS_CHECKED;
		else
		{
			minfo.fState = MFS_UNCHECKED;
			SetColumnWidth(i, 0);
		}

		int w = GetColumnWidth(i);

		visible_.push_back(visible);
		widths_.push_back(w);
		order_.push_back(i);

		menu.InsertMenuItem(menu.GetMenuItemCount(), false, &minfo);
		return i;
	}

	void SetSort(bool auto_sort=false)
	{
		auto_sort_ = auto_sort;

		//MENUITEMINFO minfo = {sizeof(MENUITEMINFO)};
		
		//minfo.fMask = MIIM_STATE;
		//minfo.fState = auto_sort_ ? MFS_CHECKED : MFS_UNCHECKED;
		
		//menu_.SetMenuItemInfo(ID_LVM_AUTOSORT, false, &minfo);

		m_bSortDescending = descending_;
		if (sort_col_ >= 0 && sort_col_ < m_arrColSortType.GetSize())
			SetSortColumn(sort_col_);
	}

	void SetColumnOrderState()
	{
		while ((int)order_.size() < header_.GetItemCount())
			order_.push_back(header_.GetItemCount());

		GetColumnOrderArray(order_.size(), &order_[0]);
	}

	void SetSortState()
	{
		MENUITEMINFO minfo = {sizeof(MENUITEMINFO)};
		
		minfo.fMask = MIIM_STATE;
		minfo.fState = auto_sort_ ? MFS_CHECKED : MFS_UNCHECKED;
		
//		menu_.SetMenuItemInfo(ID_LVM_AUTOSORT, false, &minfo);

		if (sort_col_ >= 0 && sort_col_ < m_arrColSortType.GetSize())
			SetSortColumn(sort_col_);
	}
	
	bool OnNameChecked(int i)
	{
//		try_update_lock<thisClass> lock(*this);

		while ((int)order_.size() < header_.GetItemCount())
			order_.push_back(header_.GetItemCount());

		if (!visible_[i])
		{		
			GetColumnOrderArray(order_.size(), &order_[0]);
			SetColumnWidth(i, widths_[i]);

			order_.erase(std::find(order_.begin(), order_.end(), i));
			
			int index = i + std::count(visible_.begin()+i, visible_.end(), false) - 1;
			order_.insert(order_.begin()+index, i);

			SetColumnOrderArray(order_.size(), &order_[0]);
			visible_[i] = true;
		}
		else
		{
			widths_[i] = GetColumnWidth(i);	
			GetColumnOrderArray(order_.size(), &order_[0]);

			SetColumnWidth(i, 0);

			order_.erase(std::find(order_.begin(), order_.end(), i));
			order_.insert(order_.begin(), i);

			SetColumnOrderArray(order_.size(), &order_[0]);
			visible_[i] = false;
		}
		
		MENUITEMINFO minfo = {sizeof(MENUITEMINFO)};
	
		minfo.fMask = MIIM_STATE;
		minfo.fState = visible_[i] ? MFS_CHECKED : MFS_UNCHECKED;
	
		header_.Menu().SetMenuItemInfo(i+SortHeaderCtrl::COL_MENU_NAMES_ID_START, false, &minfo);
	
		InvalidateRect(NULL, true);
		return visible_[i];
	}

	LRESULT OnAutoSort(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
	{
		auto_sort_ = !auto_sort_;
		
		MENUITEMINFO minfo = {sizeof(MENUITEMINFO)};
		
		minfo.fMask = MIIM_STATE;
		minfo.fState = auto_sort_ ? MFS_CHECKED : MFS_UNCHECKED;
		
		menu_.SetMenuItemInfo(ID_LVM_AUTOSORT, false, &minfo);
		
		return 0;
	}

	LRESULT OnRClick(int i, LPNMHDR pnmh, BOOL&)
	{
		LPNMITEMACTIVATE pia = (LPNMITEMACTIVATE)pnmh;
		
		if (menu_)
		{
			assert (menu_.IsMenu());
	
			POINT ptPoint;
			GetCursorPos(&ptPoint);
			menu_.TrackPopupMenu(0, ptPoint.x, ptPoint.y, m_hWnd);
		}

		return 0;
	}

	friend class boost::serialization::access;
	template<class Archive>
    void save(Archive & ar, const unsigned int version) const
    {
		for (size_t i=0; i<widths_.size(); ++i)
		{
			if (visible_[i])
				widths_[i] = GetColumnWidth(i);
		}

		GetColumnOrderArray(order_.size(), &order_[0]);
		sort_col_ = GetSortColumn();
		descending_ = IsSortDescending();	

		using boost::serialization::make_nvp;

		ar & make_nvp("widths", widths_);
		ar & make_nvp("order", order_);
		ar & make_nvp("visible", visible_);
		ar & make_nvp("auto_sort", auto_sort_);

		ar & make_nvp("descending", descending_);
		ar & make_nvp("sort_col", sort_col_);
    }

    template<class Archive>
    void load(Archive & ar, const unsigned int version)
    {
		using boost::serialization::make_nvp;

		ar & make_nvp("widths", widths_);
		ar & make_nvp("order", order_);
		ar & make_nvp("visible", visible_);
		ar & make_nvp("auto_sort", auto_sort_);

		ar & make_nvp("descending", descending_);
		ar & make_nvp("sort_col", sort_col_);
		
		SetColumnOrderArray(order_.size(), &order_[0]);

		m_bSortDescending = descending_;
		if (sort_col_ >= 0 && sort_col_ < m_arrColSortType.GetSize())
			SetSortColumn(sort_col_);

		for (size_t i=0; i<widths_.size(); ++i)
		{
			SetColumnWidth(i, widths_[i]);
			if (!visible_[i])
			{
				visible_[i] = true;
				OnNameChecked(i);
			}
		}

		SetColumnOrderState();
		SetSortState();
    }

    BOOST_SERIALIZATION_SPLIT_MEMBER()

	bool autoSort() { return auto_sort_; }
	
	void ConditionallyDoAutoSort()
	{
		int iCol = GetSortColumn();
		if (autoSort() && iCol >= 0 && iCol < m_arrColSortType.GetSize())
			DoSortItems(iCol, IsSortDescending());	
	}		
	
protected:	

	WTL::CMenu menu_;
	SortHeaderCtrl header_;	

	mutable std::vector<int> widths_;
	mutable std::vector<int> order_;
	mutable std::vector<bool> visible_;
	
	mutable bool auto_sort_;
	mutable bool descending_;
	mutable int sort_col_;	
};

}

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -