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

📄 groupview.cpp.svn-base

📁 wince c++ 下 开发的 rss 阅读器源代码
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:

	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;
}

BOOL CGroupView::DeleteItem(HGROUPITEM hItem) {
	return TRUE;
}

BOOL CGroupView::DeleteAllItems() {
	RootItem.Childs.RemoveAll();
	while (!Items.IsEmpty())
		delete Items.RemoveHead();

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

	return TRUE;
}

void CGroupView::AdjustViewTop() {

	if (m_nViewTop < 0)
		m_nViewTop = 0;
	else if (m_nTotalHeight > m_nClientHeight) {
		int max = m_nTotalHeight - m_nClientHeight;
		if (m_nViewTop > max)
			m_nViewTop = max;
	}
	else if (m_nTotalHeight <= m_nClientHeight) {
		m_nViewTop = 0;
	}
}


BOOL CGroupView::EnsureVisible(HGROUPITEM hItem) {
	GVITEM *gi = Items.GetAt(hItem);

	int i = m_nViewTop;
	int y = Items.GetAt(hItem)->yTop;
	if (y < m_nViewTop)
		m_nViewTop = y;
	else if (y + SCALEY(ItemHeight) > m_nViewTop + m_nClientHeight)
		m_nViewTop = y + SCALEY(ItemHeight) - m_nClientHeight;

	if (i - m_nViewTop)
		ScrollWindowEx(0, i - m_nViewTop, &m_rcScroll, &m_rcScroll, NULL, NULL, SW_INVALIDATE);

	UpdateScrollBars();

	return TRUE;
}

// message handlers

BOOL CGroupView::OnEraseBkgnd(CDC *pDC) {
	return TRUE;
}

void CGroupView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar) {
	int i = m_nViewTop;
	switch (nSBCode) {
		case SB_LINEDOWN:   m_nViewTop += SCALEY(ItemHeight); break;
		case SB_LINEUP:     m_nViewTop -= SCALEY(ItemHeight); break;
		case SB_PAGEDOWN:   m_nViewTop += m_nClientHeight; break;
		case SB_PAGEUP:     m_nViewTop -= m_nClientHeight; break;
		case SB_THUMBTRACK: {
			SCROLLINFO si;
			si.cbSize = sizeof(si);
			si.fMask = SIF_TRACKPOS;
			m_oVScrollBar.GetScrollInfo(&si);
			m_nViewTop = si.nTrackPos;
		}
	}

	AdjustViewTop();

	ScrollWindowEx(0, i - m_nViewTop, &m_rcScroll, &m_rcScroll, NULL, NULL, SW_INVALIDATE);
	m_oVScrollBar.SetScrollPos(m_nViewTop, TRUE);
	UpdateWindow();
}

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

	BOOL visible = m_oVScrollBar.IsWindowVisible();

	if (m_nClientHeight >= m_nTotalHeight) {
		m_oVScrollBar.ShowScrollBar(FALSE);
	}
	else {
		m_oVScrollBar.ShowScrollBar(TRUE);

		SCROLLINFO sbi = { 0 };
		sbi.cbSize = sizeof(sbi);
		sbi.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
		sbi.nMin = 0;
		sbi.nMax = m_nTotalHeight - 1;
		sbi.nPage = m_nClientHeight;
		sbi.nPos = m_nViewTop;
		m_oVScrollBar.SetScrollInfo(&sbi);
	}
}

void CGroupView::OnSize(UINT nType, int cx, int cy) {
	CView::OnSize(nType, cx, cy);

	m_nClientHeight = cy;
	m_nClientWidth = cx + SCALEX(1);

	CRect rcClient;
	GetClientRect(rcClient);

	m_rcScroll = rcClient;

	// place the scroll bar
	CRect rcVert;
	rcVert.top    = -SCALEY(1);
	rcVert.bottom = rcClient.bottom + SCALEY(1);
	rcVert.right  = rcClient.right + SCALEX(1);
	rcVert.left   = rcVert.right - GetSystemMetrics(SM_CXVSCROLL);

	m_oVScrollBar.SetWindowPos(NULL, rcVert.left, rcVert.top, rcVert.Width(), rcVert.Height(), SWP_NOZORDER);

	UpdateScrollBars();

	Invalidate();
}

void CGroupView::InvalidateItem(HGROUPITEM hItem, BOOL erase/* = TRUE*/) {
	if (hItem == NULL)
		return;

	GVITEM *gi = Items.GetAt(hItem);
	if (gi == NULL)
		return;

	CRect rcClient;
	GetClientRect(&rcClient);

	CRect rc(rcClient.left, gi->yTop - m_nViewTop, rcClient.right, gi->yTop + SCALEY(ItemHeight) - m_nViewTop);

	CRect rcInv;
	if (rcInv.IntersectRect(rcClient, rc)) {
		InvalidateRect(rcInv, erase);
	}
}

HGROUPITEM CGroupView::ItemFromPoint(CPoint pt) {
	POSITION pos = Items.GetHeadPosition();
	while (pos != NULL) {
		POSITION posPrev = pos;
		GVITEM *gi = Items.GetNext(pos);
		if (gi->yTop != -1) {
			if (gi->yTop - m_nViewTop <= pt.y && pt.y <= gi->yTop + SCALEY(ItemHeight) - m_nViewTop) {
				return (HGROUPITEM) posPrev;
			}
		}
	}

	return NULL;
}

// Normal

void CGroupView::OnLButtonDownNormal(UINT nFlags, CPoint point) {
	SetFocus();

	HGROUPITEM item = ItemFromPoint(point);
	if (item != NULL) {
		m_hClickedItem = item;
		LastCursorPos = point;

		HGROUPITEM hOldItem = m_hSelectedItem;
		SelectItem(m_hClickedItem);
		InvalidateItem(hOldItem, FALSE);
		InvalidateItem(m_hClickedItem, FALSE);

		SHRGINFO shrgi = {0};
		shrgi.cbSize        = sizeof(SHRGINFO);
		shrgi.hwndClient    = m_hWnd;
		shrgi.ptDown.x      = point.x;
		shrgi.ptDown.y      = point.y;
		shrgi.dwFlags       = SHRG_RETURNCMD;

		if (GN_CONTEXTMENU == ::SHRecognizeGesture(&shrgi)) {
			m_hClickedItem = NULL;

			CPoint pt = point;
			ClientToScreen(&pt);
			ContextMenu(&pt);
		}
		else
			Default();
	}
	else {
		// tap out of items (deselect all)
		HGROUPITEM hOldItem = m_hSelectedItem;

		m_hSelectedItem = NULL;
		InvalidateItem(hOldItem, FALSE);
	}
}

void CGroupView::OnLButtonUpNormal(UINT nFlags, CPoint point) {
	HGROUPITEM hItem = ItemFromPoint(point);
	if (m_hClickedItem != NULL && hItem != NULL && hItem == m_hClickedItem) {
		if (ItemHasChildren(m_hClickedItem))
			ToggleItem(m_hClickedItem);
		else
			OnItemClicked();
	}
	m_hClickedItem = NULL;
}

// TOUCH

void CGroupView::OnLButtonDownTouch(UINT nFlags, CPoint point) {
	HGROUPITEM item = ItemFromPoint(point);
	if (item != NULL) {
		m_hClickedItem = item;
		LastCursorPos = point;

		SHRGINFO shrgi = { 0 };
		shrgi.cbSize        = sizeof(SHRGINFO);
		shrgi.hwndClient    = m_hWnd;
		shrgi.ptDown.x      = point.x;
		shrgi.ptDown.y      = point.y;
		shrgi.dwFlags       = SHRG_RETURNCMD;

		if (GN_CONTEXTMENU == ::SHRecognizeGesture(&shrgi)) {
			HGROUPITEM hOldItem = m_hSelectedItem;
			SelectItem(m_hClickedItem);
			InvalidateItem(hOldItem, FALSE);
			InvalidateItem(m_hClickedItem, FALSE);

			CPoint pt = point;
			ClientToScreen(&pt);
			ContextMenu(&pt);

			m_hClickedItem = NULL;
		}
		else {
			SetCapture();
			Default();
		}
	}
	else {
		// tap out of items (deselect all)
		HGROUPITEM hOldItem = m_hSelectedItem;

		m_hSelectedItem = NULL;
		InvalidateItem(hOldItem, FALSE);
	}
}

void CGroupView::OnMouseMoveTouch(UINT nFlags, CPoint pt) {
	if (abs(pt.x - LastCursorPos.x) > SCALEX(3) || abs(pt.y - LastCursorPos.y) > SCALEX(3))
		m_hClickedItem = NULL;

	// Scrolling
	if (m_nTotalHeight > m_nClientHeight && GetCapture() == this) {
		int delta = LastCursorPos.y - pt.y;

		int top = m_nViewTop;
		m_nViewTop += delta;

		AdjustViewTop();

		ScrollWindowEx(0, top - m_nViewTop, &m_rcScroll, &m_rcScroll, NULL, NULL, SW_INVALIDATE);
		m_oVScrollBar.SetScrollPos(m_nViewTop, TRUE);
		UpdateWindow();

		LastCursorPos = pt;
	}
}

void CGroupView::OnLButtonUpTouch(UINT nFlags, CPoint point) {
	ReleaseCapture();

	HGROUPITEM hItem = ItemFromPoint(point);
	if (m_hClickedItem != NULL) {
		if (hItem != NULL && hItem == m_hClickedItem) {
			SelectItem(m_hClickedItem);

			if (ItemHasChildren(m_hClickedItem))
				ToggleItem(m_hClickedItem);
			else
				OnItemClicked();
		}
		else {

		}
	}
	m_hClickedItem = NULL;
}

void CGroupView::OnLButtonDown(UINT nFlags, CPoint point) {
	switch (Config.NavigationType) {
		case NAVIGATION_NORMAL: OnLButtonDownNormal(nFlags, point); break;
		default:
		case NAVIGATION_TOUCH: OnLButtonDownTouch(nFlags, point); break;
	}
}

void CGroupView::OnMouseMove(UINT nFlags, CPoint pt) {
	switch (Config.NavigationType) {
		case NAVIGATION_NORMAL: CView::OnMouseMove(nFlags, pt); break;
		default:
		case NAVIGATION_TOUCH: OnMouseMoveTouch(nFlags, pt); break;
	}
}

void CGroupView::OnLButtonUp(UINT nFlags, CPoint point) {
	switch (Config.NavigationType) {
		case NAVIGATION_NORMAL: OnLButtonUpNormal(nFlags, point); break;
		default:
		case NAVIGATION_TOUCH: OnLButtonUpTouch(nFlags, point); break;
	}
}

// keys

void CGroupView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
	LOG3(5, "CGroupView::OnKeyDown(%d, %d, %d)", nChar, nRepCnt, nFlags);

	HGROUPITEM hItem;
	switch (nChar) {
		case VK_UP:
			// move to previous visible item
			if (m_hSelectedItem != NULL) {
				hItem = GetPrevVisibleItem(m_hSelectedItem);
				if (hItem != NULL) {
					HGROUPITEM hOldItem = m_hSelectedItem;
					SelectItem(hItem);
				}
			}
			break;

		case VK_DOWN:
			// move to next visible item
			if (m_hSelectedItem == NULL) {
				hItem = GetRootItem();
				SelectItem(hItem);
			}
			else {
				hItem = GetNextVisibleItem(m_hSelectedItem);
				if (hItem != NULL) {
					SelectItem(hItem);
				}
			}
			break;

		case VK_LEFT:
			CollapseItem(m_hSelectedItem);
			break;

		case VK_RIGHT:
			ExpandItem(m_hSelectedItem);
			break;

		case VK_RETURN:
			if (!(nFlags & 0x4000)) {
				m_bOpenCtxMenu = FALSE;
				SetTimer(CtxMenuTimer, TIMER_KEY_CTX_MENU, NULL);
			}
			break;

		default:
			CView::OnKeyDown(nChar, nRepCnt, nFlags);
			break;
	}
}

void CGroupView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) {
	LOG3(5, "CGroupView::OnKeyUp(%d, %d, %d)", nChar, nRepCnt, nFlags);

	switch (nChar) {
		case VK_RETURN:
			KillTimer(CtxMenuTimer);
			if (m_bOpenCtxMenu) {
				m_bOpenCtxMenu = FALSE;

				if (Items.GetCount() > 0 && m_hSelectedItem != NULL) {
					GVITEM *gi = Items.GetAt(m_hSelectedItem);
					CPoint pt(m_nClientWidth / 2, gi->yTop - m_nViewTop + SCALEY(ItemHeight / 2));
					ClientToScreen(&pt);
					ContextMenu(&pt);
				}
				else
					CWnd::OnKeyUp(nChar, nRepCnt, nFlags);
			}
			else {
				if (Items.GetCount() > 0 && m_hSelectedItem != NULL) {
					// toggle item state
					if (ItemHasChildren(m_hSelectedItem))
						ToggleItem(m_hSelectedItem);
					else
						OnItemClicked();
				}
				CView::OnKeyUp(nChar, nRepCnt, nFlags);
			}
			break;

		case VK_APPS: {
			CPoint pt;
			GVITEM *gi = Items.GetAt(m_hSelectedItem);
			pt.x = m_nClientWidth / 2;
			pt.y = gi->yTop - m_nViewTop + SCALEY(ItemHeight / 2);

			ClientToScreen(&pt);

			ContextMenu(&pt);
			} break;

		default:
			CView::OnKeyUp(nChar, nRepCnt, nFlags);
			break;
	}
}

void CGroupView::ContextMenu(CPoint *pt) {
	LOG0(5, "CGroupView::ContextMenu()");

}

void CGroupView::OnTimer(UINT nIDEvent) {
	LOG0(5, "CGroupView::OnTimer()");

	if (nIDEvent == CtxMenuTimer) {
		m_bOpenCtxMenu = TRUE;
		KillTimer(CtxMenuTimer);
	}

	CView::OnTimer(nIDEvent);
}

void CGroupView::ExpandItem(HGROUPITEM hItem) {
	LOG0(1, "CGroupView::ExpandItem()");

	if (hItem == NULL)
		return;

	GVITEM *gi = Items.GetAt(hItem);
	if (gi->State == GVIS_EXPANDED || gi->Childs.GetCount() <= 0)
		return;
	gi->State = GVIS_EXPANDED;

	int top = gi->yTop;
	HGROUPITEM hNext = hItem;
	while (hNext != NULL) {
		UpdateItemsY(hNext, top);
		hNext = GetNextSiblingItem(hNext);
	}

//	LOG1(1, "- diff = %d", top - m_nTotalHeight);
	int diff = top - m_nTotalHeight + SCALEY(ItemHeight);
	if (gi->yTop + diff > m_nViewTop + m_nClientHeight) {
		m_nViewTop = gi->yTop + diff - m_nClientHeight;
		if (gi->yTop < m_nViewTop)
			m_nViewTop = gi->yTop;
	}
	m_nTotalHeight = top;

	Invalidate(FALSE);
	AdjustViewTop();
	UpdateScrollBars();
}

void CGroupView::CollapseItem(HGROUPITEM hItem) {
	LOG0(5, "CGroupView::CollapseItem()");

	if (hItem == NULL)
		return;

	GVITEM *gi = Items.GetAt(hItem);
	if (gi->State == GVIS_COLLAPSED || gi->Childs.GetCount() <= 0)
		return;
	gi->State = GVIS_COLLAPSED;

	int top = gi->yTop;
	int t = -1;
	HGROUPITEM hNext = hItem;
	UpdateItemsY(hNext, t);
	gi->yTop = top;
	top += SCALEY(ItemHeight);

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

	m_nTotalHeight = top;

	Invalidate(FALSE);
	AdjustViewTop();
	UpdateScrollBars();
}

void CGroupView::ToggleItem(HGROUPITEM hItem) {
	LOG1(5, "CGroupView::ToggleItem(%d)", hItem);

	if (hItem == NULL)
		return;

	if (GetItemState(hItem, 0) == GVIS_EXPANDED)
		CollapseItem(hItem);
	else if (GetItemState(hItem, 0) == GVIS_COLLAPSED)
		ExpandItem(hItem);
}

void CGroupView::SelectItem(HGROUPITEM hItem) {
	LOG1(5, "CGroupView::SelectItem(%d)", hItem);

	HGROUPITEM hOldItem = m_hSelectedItem;
	EnsureVisible(hItem);
	m_hSelectedItem = hItem;
	InvalidateItem(hOldItem, FALSE);
	InvalidateItem(m_hSelectedItem, FALSE);
}

void CGroupView::OnItemClicked() {
}

void CGroupView::UpdateItemHeight() {
	int items = m_nTotalHeight / SCALEY(ItemHeight);
	m_nTotalHeight = items * SCALEY(ItemHeight);
	int top = 0;
	HGROUPITEM hItem = GetRootItem();
	while (hItem != NULL) {
		UpdateItemsY(hItem, top);
		hItem = GetNextSiblingItem(hItem);
	}

	CreateFonts();
	UpdateScrollBars();
	Invalidate();
}

⌨️ 快捷键说明

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