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