📄 groupview.cpp.svn-base
字号:
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 + -