📄 booktreeview.cpp
字号:
// GUI/BookTreeView.cpp : 实现文件
//
#include "stdafx.h"
#include "KingBook.h"
#include "BookTreeView.h"
#include "KingBookDoc.h"
using namespace Library;
using namespace std;
// CBookTreeView
IMPLEMENT_DYNCREATE(CBookTreeView, CTreeView)
CBookTreeView::CBookTreeView()
{
}
CBookTreeView::~CBookTreeView()
{
}
BEGIN_MESSAGE_MAP(CBookTreeView, CTreeView)
ON_WM_CREATE()
ON_NOTIFY_REFLECT(NM_RCLICK, &CBookTreeView::OnNMRclick)
ON_NOTIFY_REFLECT(NM_CLICK, &CBookTreeView::OnNMClick)
ON_NOTIFY_REFLECT(TVN_SELCHANGED, &CBookTreeView::OnTvnSelchanged)
END_MESSAGE_MAP()
// CBookTreeView 诊断
#ifdef _DEBUG
void CBookTreeView::AssertValid() const
{
CTreeView::AssertValid();
}
#ifndef _WIN32_WCE
void CBookTreeView::Dump(CDumpContext& dc) const
{
CTreeView::Dump(dc);
}
#endif
#endif //_DEBUG
// CBookTreeView 消息处理程序
/// <summary>创建窗口, 创建树状视图, 并添加几个根节点</summary>
/// <param name="lpCreateStruct">创建树状视图的样式</param>
/// <returns>成功返回 0.</returns>
/// <exception>NULL</exception>
/// <remarks>
/// 修改视图的样式; 添加根节点:"我的电子书", "收藏夹", "最近浏览", "所有图书"
/// </remarks>
int CBookTreeView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
lpCreateStruct->style = lpCreateStruct->style | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_LINESATROOT |TVS_HASLINES |TVS_NOHSCROLL ;// |TVS_CHECKBOXES ;
if (CTreeView::OnCreate(lpCreateStruct) == -1)
return -1;
CTreeCtrl* pTreeCtrl = &(this->GetTreeCtrl());
TVINSERTSTRUCT rootItem;
HTREEITEM root; // 我的电子书节点
rootItem.hInsertAfter = TVI_LAST;
rootItem.hParent = NULL;
rootItem.item.mask = TVIF_TEXT|TVIF_PARAM;
rootItem.item.pszText = _T("我的电子书");
bookClassID.push_back(IDS_BOOKCLASS_ROOT);
rootItem.item.lParam = (LPARAM)bookClassID.size() - 1;
root = pTreeCtrl->InsertItem(&rootItem);
rootItem.item.pszText = _T("收藏夹");
bookClassID.push_back(IDS_FAVORITE);
rootItem.item.lParam = (LPARAM)bookClassID.size() - 1;
pTreeCtrl->InsertItem(&rootItem);
rootItem.item.pszText = _T("最近浏览");
bookClassID.push_back(IDS_RECENT);
rootItem.item.lParam = (LPARAM)bookClassID.size() - 1;
pTreeCtrl->InsertItem(&rootItem);
rootItem.item.pszText = _T("所有图书");
bookClassID.push_back(IDS_ALL_BOOK);
rootItem.item.lParam = (LPARAM)bookClassID.size() - 1;
pTreeCtrl->InsertItem(&rootItem);
//HTREEITEM bokClass = pTreeCtrl->InsertItem(_T("我的电子书"));
//HTREEITEM favo = pTreeCtrl->InsertItem(_T("收藏夹"));
//HTREEITEM rece = pTreeCtrl->InsertItem(_T("最近浏览"));
//HTREEITEM allBook = pTreeCtrl->InsertItem(_T("所有图书"));
return 0;
TVINSERTSTRUCT tvInsert;
std::vector<BookClass> roots;
((CKingBookDoc*)this->GetDocument())->bookLib.GetRootBookClass(roots);
for(int i = 0; i < roots.size(); i ++)
{
tvInsert.hInsertAfter = TVI_LAST;
tvInsert.hParent = root;
tvInsert.item.mask = TVIF_TEXT|TVIF_PARAM;
// MessageBox(roots[i].GetName().c_str());
tvInsert.item.pszText = const_cast<LPSTR>(roots[i].GetName().c_str());
// 将这个图书分类的ID保存到 结尾
bookClassID.push_back(roots[i].GetID());
tvInsert.item.lParam = (LPARAM)bookClassID.size() - 1;//
pTreeCtrl->InsertItem(&tvInsert);
// MessageBox((LPTSTR)tvInsert.item.lParam);
}
return 0;
}
/// <summary>在视图里右击, 并视情况弹出菜单.</summary>
/// <param>忽略</param>
/// <returns>void</returns>
/// <exception>NULL</exception>
/// <remarks>
/// <b>步骤:</b>
/// <list type="number">
/// <item><description>得到鼠标位置, 并判断鼠标是否击中视图中的一个节点</description></item>
/// <item><description>选中鼠标击中的这个节点</description></item>
/// <item><description>得到选中节点对应的图书分类的ID</description></item>
/// <item><description>如果:分类是"收藏夹", "最近浏览", "所有图书", 没有操作</description></item>
/// <item><description>如果选中的是某个图书分类, 创建菜单.</description></item>
/// </list>
/// </remarks>
void CBookTreeView::OnNMRclick(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO: 在树上右击
CTreeCtrl* pTreeCtrl = &(this->GetTreeCtrl());
CPoint pt;
GetCursorPos(&pt);
ScreenToClient(&pt);
HTREEITEM hitItem = pTreeCtrl->HitTest(pt);
if(hitItem == NULL)
{
*pResult = 0;
return ;
}
pTreeCtrl->Select(hitItem, TVGN_CARET);
HTREEITEM sel = pTreeCtrl->GetSelectedItem();
int idIndex = (int)pTreeCtrl->GetItemData(sel);
std::string clsID = this->bookClassID[idIndex];
if(clsID == IDS_ALL_BOOK)
{
}
else if( clsID == IDS_FAVORITE)
{
}
else if( clsID == IDS_RECENT)
{
}
else // 击中普通的图书分类
{
// 弹出菜单
CMenu mHitItem;
mHitItem.LoadMenu(IDR_TV_HIT_ITEM);
CMenu *subMenu;
subMenu = mHitItem.GetSubMenu(0);
ClientToScreen(&pt);
subMenu->TrackPopupMenu(0, pt.x, pt.y, this);
}
*pResult = 0;
}
BOOL CBookTreeView::PreCreateWindow(CREATESTRUCT& cs)
{
return CTreeView::PreCreateWindow(cs);
}
/// <summary>鼠标左键点击事件</summary>
/// <param>忽略</param>
/// <returns>void</returns>
/// <exception>NULL</exception>
/// <remarks>如果鼠标击中了一个节点(图书分类), 更新这个节点
/// </remarks>
void CBookTreeView::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult)
{
CTreeCtrl* pTreeCtrl = &(this->GetTreeCtrl());
CPoint pt;
GetCursorPos(&pt);
ScreenToClient(&pt);
HTREEITEM hitItem = pTreeCtrl->HitTest(pt);
//this->MessageBox(_T("鼠标左键"), _T("Tree View"));
if(hitItem != NULL) // 点在某个分支上, 判断是否有子节点, 是否需要加载
{
pTreeCtrl->Select(hitItem, TVGN_CARET);
HTREEITEM selItem = pTreeCtrl->GetSelectedItem();
//更新树节点--图书分类,的子分类和包含的图书
this->UpdateBookClassItem(selItem);
}
*pResult = 0;
}
/// <summary>更新树节点--图书分类,的子分类和包含的图书</summary>
/// <param name="bookClassItem">树状视图的节点, 应当是一个图书分类</param>
/// <returns>成功返回true, 失败返回false</returns>
/// <exception>调用的函数可能抛出异常</exception>
/// <remarks>加载这个分类的子分类, 加载包含的图书 , -- 如果存在的话</remarks>
bool CBookTreeView::UpdateBookClassItem(HTREEITEM bookClassItem)
{
CTreeCtrl* pTreeCtrl = &(this->GetTreeCtrl());
CKingBookDoc* pDoc = (CKingBookDoc*)this->GetDocument();
// 得到选中节点图书分类的ID
int idIndex = (int)pTreeCtrl->GetItemData(bookClassItem);
// TODO:是"所有图书"节点?
if(this->bookClassID[idIndex] == IDS_ALL_BOOK)
{
//return true;
}
else if(pTreeCtrl->GetChildItem(bookClassItem) == NULL)// 其他节点
{
// 判断是否存在子节点
// 没有子节点,加载
std::vector<BookClass> subClass;
pDoc->bookLib.GetSubsOfClass(BookObject(this->bookClassID[idIndex]), subClass);
TVINSERTSTRUCT tvInsert;
for(int i = 0; i < subClass.size(); i ++)
{
tvInsert.hInsertAfter = TVI_LAST;
tvInsert.hParent = bookClassItem;
tvInsert.item.mask = TVIF_TEXT|TVIF_PARAM;
tvInsert.item.pszText = const_cast<LPSTR>(subClass[i].GetName().c_str());
// 将这个图书分类的ID保存到 结尾
bookClassID.push_back(subClass[i].GetID());
tvInsert.item.lParam = (LPARAM)bookClassID.size() - 1;//
pTreeCtrl->InsertItem(&tvInsert);
}
}
// TODO: 加载包含的图书, 通过Doc类通知ListView
pDoc->SetShownBookClass( this->bookClassID[idIndex]);
// 更新视图
pDoc->UpdateAllViews(this, IDUP_TREEVIEW);
return true;
}
/// <summary>视图中选定项发生了改变</summary>
/// <param>忽略</param>
/// <returns>void</returns>
/// <exception>NULL</exception>
/// <remarks>更新选定项的信息
/// </remarks>
void CBookTreeView::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
CTreeCtrl* pTreeCtrl = &(this->GetTreeCtrl());
selItem = pTreeCtrl->GetSelectedItem();
this->UpdateBookClassItem(selItem);
*pResult = 0;
}
/// <summary>更新视图</summary>
/// <param name="lHint">[IN]更新原因代码</param>
/// <returns>void</returns>
/// <exception>NULL</exception>
/// <remarks>lHint 为IDUP_DOC_BOOKCLASS_ADD, IDUP_DOC_BOOKCLASS_EDIT, IDUP_DOC_BOOKCLASS_DEL 更新视图.<br/>
///
/// </remarks>
void CBookTreeView::OnUpdate(CView* /*pSender*/, LPARAM lHint, CObject* /*pHint*/)
{
CTreeCtrl* pTreeCtrl = &(this->GetTreeCtrl());
CKingBookDoc* pDoc = (CKingBookDoc*)this->GetDocument();
if(lHint == IDUP_DOC_BOOKCLASS_ADD) // 刚才添加了分类
{
// 添加子节点
Library::BookClass subClass;
pDoc->bookLib.GetBookClassInfo(Library::BookObject(pDoc->GetShownBookClass()), subClass);
TVINSERTSTRUCT tvInsert;
tvInsert.hInsertAfter = TVI_LAST;
tvInsert.hParent = this->selItem; // 添加到刚才选定的节点
tvInsert.item.mask = TVIF_TEXT|TVIF_PARAM;
tvInsert.item.pszText = const_cast<LPSTR>(subClass.GetName().c_str());
// 将这个图书分类的ID保存到 结尾
bookClassID.push_back(subClass.GetID());
tvInsert.item.lParam = (LPARAM)bookClassID.size() - 1;//
HTREEITEM newItem = pTreeCtrl->InsertItem(&tvInsert);
// 展开selItem
pTreeCtrl->Expand(selItem, TVE_TOGGLE);
// 选中这个新的节点
pTreeCtrl->Select(newItem, TVGN_CARET);
return ;
}
else if(lHint == IDUP_DOC_BOOKCLASS_EDIT)// 刚才编辑了分类的信息
{
Library::BookClass bookClassInfo;
pDoc->bookLib.GetBookClassInfo(Library::BookObject(pDoc->GetShownBookClass()), bookClassInfo);
pTreeCtrl->SetItemText(this->selItem, bookClassInfo.GetName().c_str());
}
else if(lHint == IDUP_DOC_BOOKCLASS_DEL) // 刚才删除了分类
{
HTREEITEM parent = pTreeCtrl->GetParentItem(this->selItem);
pTreeCtrl->DeleteItem(this->selItem);
// 选中父节点, 没有父亲?天之骄子?
pTreeCtrl->Select(parent, TVGN_CARET);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -