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

📄 groupview.cpp.svn-base

📁 wince c++ 下 开发的 rss 阅读器源代码
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/**
 *  GroupView.cpp
 *
 *  Copyright (C) 2008  David Andrs <pda@jasnapaka.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "../StdAfx.h"
#include "../prssr.h"
#include "GroupView.h"

#include "../Appearance.h"
#include "../Config.h"
#include "../../share/helpers.h"

#ifdef MYDEBUG
#undef THIS_FILE
static TCHAR THIS_FILE[] = _T(__FILE__);
#include "../debug/crtdbg.h"
#define new MYDEBUG_NEW
#endif

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define CLASS_NAME						_T("PrssrGroupViewClass")

const int CGroupView::ITEM_MARGIN = 9;

BOOL CGroupView::Register() {
	// Register your unique class name that you wish to use
	WNDCLASS wndcls;

	memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL
											// defaults

	wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

	//you can specify your own window procedure
	wndcls.lpfnWndProc = ::DefWindowProc;
	wndcls.hInstance = AfxGetInstanceHandle();
	wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
	wndcls.lpszMenuName = NULL;

	// Specify your own class name for using FindWindow later
	wndcls.lpszClassName = CLASS_NAME;

	// Register the new class and exit if it fails
	if (!AfxRegisterClass(&wndcls)) {
		TRACE(_T("Class Registration Failed\n"));
		return FALSE;
	}

	return TRUE;
}

void CGroupView::Unregister() {
}

/////////////////////////////////////////////////////////////////////////////
// CGroupView

CGroupView::CGroupView() {
	RootItem.Parent = NULL;
	RootItem.State = GVIS_EXPANDED;
	RootItem.yTop = 0;

	m_nTotalHeight = 0;
	m_nViewTop = 0;
	m_hSelectedItem = NULL;

	CtxMenuTimer = 1;
	m_bOpenCtxMenu = FALSE;

	m_hClickedItem = NULL;

	ItemHeight = ITEM_MARGIN + Appearance.SummaryViewFontCfg.Size;

	NoItemsId = IDS_NO_ITEMS_TO_DISPLAY;
}

CGroupView::~CGroupView() {
	while (!Items.IsEmpty())
		delete Items.RemoveHead();
}


BEGIN_MESSAGE_MAP(CGroupView, CView)
	//{{AFX_MSG_MAP(CGroupView)
	ON_WM_CREATE()
	ON_WM_PAINT()
	ON_WM_VSCROLL()
	ON_WM_SIZE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_TIMER()
	ON_WM_KEYDOWN()
	ON_WM_KEYUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CGroupView::CreateFonts() {
	m_fntBase.DeleteObject();
	m_fntBold.DeleteObject();

	LOGFONT lf = { 0 };
	wcscpy(lf.lfFaceName, Appearance.SummaryViewFontCfg.FontFace);
	CDC *pDC = GetDC();
	lf.lfHeight = ((Appearance.SummaryViewFontCfg.Size * pDC->GetDeviceCaps(LOGPIXELSY)) / 72) + 1;
	m_fntBase.CreateFontIndirect(&lf);

	lf.lfWeight = FW_BOLD;
	m_fntBold.CreateFontIndirect(&lf);

	ReleaseDC(pDC);
}

/////////////////////////////////////////////////////////////////////////////
// CGroupView message handlers

int CGroupView::OnCreate(LPCREATESTRUCT lpCreateStruct) {
	LOG1(5, "CGroupView::OnCreate(%p)", lpCreateStruct);

	BOOL ret = CView::OnCreate(lpCreateStruct);
	if (ret == -1)
		return -1;

	CreateFonts();
	// icons
	AfxSetResourceHandle(theApp.GetDPISpecificInstanceHandle());
	m_oIcons.Create(IDB_NEWS_ITEMS, SCALEX(16), 0, RGB(255, 0, 255));
	AfxSetResourceHandle(AfxGetInstanceHandle());

	// scroll bar
	CRect rcVert;
	m_oVScrollBar.Create(SBS_VERT | WS_CHILD, rcVert, this, 1);

	UpdateScrollBars();

	return ret;
}

void CGroupView::OnDraw(CDC *pDC) {
}


void CGroupView::UpdateItemsY(HGROUPITEM hParent, int &top) {
	if (hParent == NULL)
		return;

	GVITEM *giParent = Items.GetAt(hParent);
	giParent->yTop = top;

	if (top != -1)
		top += SCALEY(ItemHeight);

	if (giParent->State == GVIS_COLLAPSED) {
		int t = -1;
		HGROUPITEM hChild = GetChildItem(hParent);
		while (hChild != NULL) {
			GVITEM *giChild = Items.GetAt(hChild);
			giChild->State = GVIS_COLLAPSED;

			UpdateItemsY(hChild, t);
			hChild = GetNextSiblingItem(hChild);
		}
	}
	else {
		HGROUPITEM hChild = GetChildItem(hParent);
		while (hChild != NULL) {
			UpdateItemsY(hChild, top);
			hChild = GetNextSiblingItem(hChild);
		}
	}
}

void CGroupView::DrawIcon(CDC &dc, int icon, BOOL selected) {
	IMAGELISTDRAWPARAMS drawing;
	drawing.cbSize = sizeof(IMAGELISTDRAWPARAMS);
	drawing.himl = m_pImageList->GetSafeHandle();
	drawing.i = icon;
	drawing.hdcDst = dc.GetSafeHdc();
	drawing.x = SCALEX(2);
	drawing.y = SCALEY(1);
	drawing.cx = SCALEX(16);
	drawing.cy = SCALEY(16);
	drawing.xBitmap = 0;
	drawing.yBitmap = 0;
	drawing.rgbBk = CLR_NONE;
	drawing.rgbFg = CLR_DEFAULT;
	if (selected)
		drawing.fStyle = ILD_BLEND50;
	else
		drawing.fStyle = ILD_NORMAL;
	drawing.dwRop = SRCCOPY;
	ImageList_DrawIndirect(&drawing);
}

void CGroupView::OnDrawItem(CDC &dc, CRect &rc, HGROUPITEM hItem, BOOL selected) {
	LOG0(5, "CGroupView::OnDrawItem");

	GVITEM *gi = Items.GetAt(hItem);

	COLORREF clrBg, clrFg, clrOld;
	if (selected) {
		clrBg = ::GetSysColor(COLOR_HIGHLIGHT);
		clrFg = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
	}
	else {
		clrBg = ::GetSysColor(COLOR_WINDOW);
		clrFg = ::GetSysColor(COLOR_WINDOWTEXT);
	}

	// background
	dc.FillSolidRect(rc, clrBg);

	int oldBkMode = dc.SetBkMode(TRANSPARENT);

	CRect rcItem = rc;

	// icon
	if (gi->Image != -1) {
		DrawIcon(dc, gi->Image, selected);
	}
	else {
		CRect rcIcon(rc.left, rc.top, rc.left + SCALEX(20), rc.bottom);
	}

	rcItem.left += SCALEX(20);

	// title
	CFont *pOldFont;
	pOldFont = dc.SelectObject(&m_fntBase);

	clrOld = dc.SetTextColor(clrFg);
	rcItem.DeflateRect(SCALEX(2), SCALEY(1), SCALEX(2), SCALEY(3));

	DrawTextEndEllipsis(dc, gi->Text, rcItem, DT_LEFT | DT_BOTTOM | DT_NOPREFIX);
	dc.SetTextColor(clrOld);
	dc.SelectObject(pOldFont);

	dc.SetBkMode(oldBkMode);
}

void CGroupView::DrawItems(CDC &dc, CRect &rc, HGROUPITEM hParent) {
	if (hParent == NULL)
		return;

	BOOL selected = (GetSelectedItem() == hParent);
	GVITEM *giParent = Items.GetAt(hParent);
	if (giParent->yTop != -1) {
		CRect rcPhys(rc.left, giParent->yTop - m_nViewTop, rc.right, giParent->yTop + SCALEY(ItemHeight) - m_nViewTop);

		CRect rcClip;
		dc.GetClipBox(rcClip);

		CRect rcDraw;
		if (rcDraw.IntersectRect(rcClip, rcPhys)) {
			// offscreen buffer
			CBitmap bmp;
			bmp.CreateCompatibleBitmap(&dc, rc.Width(), rc.Height());
			CDC memDC;
			memDC.CreateCompatibleDC(&dc);
			CBitmap *saveBmp = memDC.SelectObject(&bmp);

			CRect rcItem = rc;
			OnDrawItem(memDC, rcItem, hParent, selected);
			// copy to screen
			dc.BitBlt(0, giParent->yTop - m_nViewTop, rc.Width(), rc.Height(), &memDC, 0, 0, SRCCOPY);

			//
			memDC.SelectObject(saveBmp);
		}
	}

	if (giParent->State == GVIS_COLLAPSED) {
	}
	else {
		HGROUPITEM hChild = GetChildItem(hParent);
		while (hChild != NULL) {
			DrawItems(dc, rc, hChild);
			hChild = GetNextSiblingItem(hChild);
		}
	}
}

void CGroupView::OnPaint() {
	LOG0(5, "CGroupView::OnPaint()");

	CPaintDC dc(this); // device context for painting

	int nSavedDC = dc.SaveDC();

	CRect rc;
	GetClientRect(rc);

	if (Items.GetCount() > 0) {
		if (m_oVScrollBar.IsWindowVisible()) {
			CRect rcVScroll;
			m_oVScrollBar.GetWindowRect(rcVScroll);
			rc.right -= rcVScroll.Width() - SCALEX(1);
		}

		//
		int top = rc.top;
		int ofsY = 0;

		CRect rcItem(rc.left, 0, rc.right, SCALEY(ItemHeight));
		HGROUPITEM hRoot = GetRootItem();
		while (hRoot != NULL) {
			DrawItems(dc, rcItem, hRoot);
			hRoot = GetNextSiblingItem(hRoot);
		}

		if (m_nTotalHeight < m_nClientHeight) {
			dc.FillSolidRect(rc.left, m_nTotalHeight, rc.right, rc.bottom, Appearance.ClrSummaryBg);
		}
	}
	else {
		CString sText;
		sText.LoadString(NoItemsId);

		dc.FillSolidRect(rc, Appearance.ClrSummaryBg);
		rc.DeflateRect(SCALEX(8), SCALEY(8));

		CFont *pFont = dc.SelectObject(&Appearance.BaseFont);
		dc.SetTextColor(Appearance.ClrSummaryFg);
		dc.DrawText(sText, &rc, DT_CENTER | DT_TOP | DT_NOPREFIX | DT_WORDBREAK);
		dc.SelectObject(pFont);
	}

	dc.RestoreDC(nSavedDC);
}

// implementation

UINT CGroupView::GetCount() const {
	return Items.GetCount();
}

BOOL CGroupView::ItemHasChildren(HGROUPITEM hItem) const {
	GVITEM *gi = Items.GetAt(hItem);
	return gi->Childs.GetCount() > 0;
}

HGROUPITEM CGroupView::GetChildItem(HGROUPITEM hItem) const {
	GVITEM *gi = Items.GetAt(hItem);
	if (gi->Childs.GetCount() > 0)
		return gi->Childs.GetHead();
	else
		return NULL;
}

HGROUPITEM CGroupView::GetNextSiblingItem(HGROUPITEM hItem) const {
	GVITEM *gi = Items.GetAt(hItem);
	HGROUPITEM hParent = gi->Parent;
	const GVITEM *giParent;
	if (hParent == NULL)
		giParent = &RootItem;
	else
		giParent = Items.GetAt(hParent);

	POSITION pos = giParent->Childs.Find(hItem);
	giParent->Childs.GetNext(pos);
	if (pos != NULL)
		return giParent->Childs.GetAt(pos);
	else
		return NULL;
}

HGROUPITEM CGroupView::GetPrevSiblingItem(HGROUPITEM hItem) const {
	GVITEM *gi = Items.GetAt(hItem);
	HGROUPITEM hParent = gi->Parent;
	const GVITEM *giParent;
	if (hParent == NULL)
		giParent = &RootItem;
	else
		giParent = Items.GetAt(hParent);

	POSITION pos = giParent->Childs.Find(hItem);
	giParent->Childs.GetPrev(pos);
	if (pos != NULL)
		return giParent->Childs.GetAt(pos);
	else
		return NULL;
}

HGROUPITEM CGroupView::GetParentItem(HGROUPITEM hItem) const {
	GVITEM *gi = Items.GetAt(hItem);
	return gi->Parent;
}

HGROUPITEM CGroupView::GetRootItem() const {
	if (RootItem.Childs.GetCount() > 0)
		return RootItem.Childs.GetHead();
	else
		return NULL;
}

HGROUPITEM CGroupView::GetPrevVisibleItem(HGROUPITEM hItem) const {
	GVITEM *gi = Items.GetAt(hItem);

	HGROUPITEM hPrev = GetPrevSiblingItem(hItem);
	if (hPrev == NULL)
		return GetParentItem(hItem);
	else {
		GVITEM *giPrev = Items.GetAt(hPrev);
		while (giPrev->State == GVIS_EXPANDED) {
			hPrev = giPrev->Childs.GetTail();
			giPrev = Items.GetAt(hPrev);
		}
		return hPrev;
	}
}

HGROUPITEM CGroupView::GetNextVisibleItem(HGROUPITEM hItem) const {
	GVITEM *gi = Items.GetAt(hItem);
	if (gi->State == GVIS_COLLAPSED) {
		HGROUPITEM hNext = GetNextSiblingItem(hItem);
		if (hNext == NULL) {
			HGROUPITEM hParent = GetParentItem(hItem);
			if (hParent == NULL)
				return NULL;
			else
				return GetNextSiblingItem(hParent);
		}
		else
			return hNext;
	}
	else if (gi->State == GVIS_EXPANDED) {
		HGROUPITEM hNext = GetChildItem(hItem);
		return hNext;
	}
	else
		return NULL;
}

UINT CGroupView::GetItemState(HGROUPITEM hItem, UINT nStateMask) const {
	GVITEM *gi = Items.GetAt(hItem);
	return gi->State;
}

BOOL CGroupView::SetItemState(HGROUPITEM hItem, UINT nState, UINT nStateMask) {
	GVITEM *gi = Items.GetAt(hItem);
	gi->State = nState;
	return TRUE;
}

BOOL CGroupView::GetItemImage(HGROUPITEM hItem, int &nImage) const {
	GVITEM *gi = Items.GetAt(hItem);
	nImage = gi->Image;
	return TRUE;
}

BOOL CGroupView::SetItemImage(HGROUPITEM hItem, int nImage) {
	GVITEM *gi = Items.GetAt(hItem);
	gi->Image = nImage;
	return TRUE;
}

CString CGroupView::GetItemText(HGROUPITEM hItem) const {
	GVITEM *gi = Items.GetAt(hItem);
	return gi->Text;
}

BOOL CGroupView::SetItemText(HGROUPITEM hItem, LPCTSTR lpszItem) {
	GVITEM *gi = Items.GetAt(hItem);
	gi->Text = CString(lpszItem);
	return TRUE;
}

DWORD CGroupView::GetItemData(HGROUPITEM hItem) const {
	GVITEM *gi = Items.GetAt(hItem);
	return gi->Data;
}

BOOL CGroupView::SetItemData(HGROUPITEM hItem, DWORD dwData) {
	GVITEM *gi = Items.GetAt(hItem);
	gi->Data = dwData;
	return TRUE;
}

HGROUPITEM CGroupView::InsertItem(LPCTSTR lpszItem, HGROUPITEM hParent/* = GVI_ROOT*/, HGROUPITEM hInsertAfter/* = GVI_LAST*/) {
	LOG1(5, "CGroupView::InsertItem('%S', , )", lpszItem);

	GVITEM *giParent;

	GVITEM *giNew = new GVITEM;
	giNew->Text = CString(lpszItem);
	giNew->Image = -1;
	giNew->State = GVIS_COLLAPSED;
	if (hParent == GVI_ROOT) {
		giNew->Parent = NULL;
		giParent = &RootItem;
	}
	else {
		giNew->Parent = hParent;
		giParent = Items.GetAt(hParent);
	}

	if (giParent->State == GVIS_EXPANDED)
		m_nTotalHeight += SCALEY(ItemHeight);

	HGROUPITEM hNewItem = Items.AddTail(giNew);
	if (hInsertAfter == GVI_LAST)
		giParent->Childs.AddTail(hNewItem);
	else if (hInsertAfter == GVI_FIRST)
		giParent->Childs.AddHead(hNewItem);
	else {
		POSITION pos = giParent->Childs.Find(hInsertAfter);
		giParent->Childs.InsertAfter(pos, hNewItem);
	}

	//
	int top = 0;
	HGROUPITEM hItem = NULL;

	if (hParent == GVI_ROOT) {
		top = 0;
		hItem = GetRootItem();
	}
	else {
		top = giParent->yTop;
		hItem = hParent;
	}

	while (hItem != NULL) {
		UpdateItemsY(hItem, top);
		hItem = GetNextSiblingItem(hItem);
	}

	return hNewItem;
}

HGROUPITEM CGroupView::InsertItem(LPCTSTR lpszItem, int nImage, HGROUPITEM hParent/* = GVI_ROOT*/, HGROUPITEM hInsertAfter/* = GVI_LAST*/) {
	LOG2(5, "CGroupView::InsertItem('%S', %d, , )", lpszItem, nImage);

	GVITEM *giParent;

	GVITEM *giNew = new GVITEM;
	giNew->Text = CString(lpszItem);
	giNew->Image = nImage;
	giNew->State = GVIS_COLLAPSED;
	if (hParent == GVI_ROOT) {
		giNew->Parent = NULL;
		giParent = &RootItem;
	}
	else {
		giNew->Parent = hParent;
		giParent = Items.GetAt(hParent);
	}

	if (giParent->State == GVIS_EXPANDED)
		m_nTotalHeight += SCALEY(ItemHeight);

⌨️ 快捷键说明

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