📄 mytreeview.cpp
字号:
// MyTreeView.cpp : implementation file
//
#include "stdafx.h"
#include "ChatClient.h"
#include "MyTreeView.h"
#include "ClientLog.h"
#include "SendMessageDlg.h"
#include "ClientFormView.h"
#include "MainFrm.h"
#include "ShowMessage.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMyTreeView
IMPLEMENT_DYNCREATE(CMyTreeView, CTreeView)
CMyTreeView::CMyTreeView():m_Tree(GetTreeCtrl())
{
}
CMyTreeView::~CMyTreeView()
{
POSITION pos;
pos = m_ClientNameList.GetHeadPosition();
POSITION tempos = pos;
if(pos)
{
int iCount = m_ClientNameList.GetCount();
for(int i = 0;i < iCount; i ++)
{
tempos = pos;
Client * pTempClient = (Client *)m_ClientNameList.GetNext(pos);
delete pTempClient;
m_ClientNameList.RemoveAt(tempos);
}
}
}
BEGIN_MESSAGE_MAP(CMyTreeView, CTreeView)
//{{AFX_MSG_MAP(CMyTreeView)
ON_WM_CREATE()
ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
ON_COMMAND(ID_JOININROOM, OnJoininroom)
ON_COMMAND(ID_MENU_SEND, OnMenuSend)
ON_WM_LBUTTONDBLCLK()
ON_NOTIFY_REFLECT(NM_RDBLCLK, OnRclick)
ON_NOTIFY_REFLECT(NM_DBLCLK, OnRclick)
ON_WM_TIMER()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_ADDNEWROOM,AddNewRoom)
ON_MESSAGE(WM_NEWCLIENTCOMEIN,OnNewClientIn)
ON_MESSAGE(WM_USERLOGOUT,OnClientOut)
ON_MESSAGE(WM_SAYINPRIVATE,OnSayInPrivate)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMyTreeView drawing
void CMyTreeView::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
// TODO: add draw code here
}
/////////////////////////////////////////////////////////////////////////////
// CMyTreeView diagnostics
#ifdef _DEBUG
void CMyTreeView::AssertValid() const
{
CTreeView::AssertValid();
}
void CMyTreeView::Dump(CDumpContext& dc) const
{
CTreeView::Dump(dc);
}
#endif //_DEBUG
extern CChatClientApp theApp;
void CMyTreeView::AddNewRoom(Message wParam,LPARAM lParam)
{
//CString
CMainFrame * m_pMainFrame = (CMainFrame *)AfxGetMainWnd();
ASSERT_VALID(m_pMainFrame);
ASSERT(m_pMainFrame != NULL);
static int iTimes = 1;
if(iTimes == 1)
{
AfxGetMainWnd()->ShowWindow(SW_SHOWNORMAL);
m_pMainFrame ->GetFormView()->SetDlgItemText(IDC_SELFNAME,theApp.m_skMainSocket.GetUserName());
iTimes ++;
}
Message msObj = wParam;
CString strRoom = msObj.strRoom;
m_Tree.InsertItem(strRoom,2,3,m_ParentItem);
// m_Tree.InsertItem("strRoom",2,3,m_ParentItem);
m_Tree.Expand(m_ParentItem,TVE_EXPAND);
}
/////////////////////////////////////////////////////////////////////////////
// CMyTreeView message handlers
int CMyTreeView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CTreeView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
m_ImageList.Create(IDB_IMAGELIST,16,5,RGB(255,0,255));
m_Tree.SetImageList(&m_ImageList,TVSIL_NORMAL);
m_ParentItem = m_Tree.InsertItem("聊天室列表",2,3);
return 0;
}
extern CChatClientApp theApp;
void CMyTreeView::OnRclick(NMHDR* pNMHDR, LRESULT* pResult)
{
CMenu menu;
CMenu * pContextMenu;
POINT point;
GetCursorPos(&point);
// CTreeView::OnLButtonDown(0,point);
ScreenToClient(&point);
HTREEITEM hItem = m_Tree.GetSelectedItem();
CRect rect;
m_Tree.GetItemRect(hItem,&rect,TRUE);
if(rect.PtInRect(point))
{
if(m_Tree.GetParentItem(hItem) == m_ParentItem)
{
menu.LoadMenu(IDR_JOINROOM);
pContextMenu = menu.GetSubMenu(0);
ClientToScreen(&point);
pContextMenu->TrackPopupMenu(TPM_LEFTBUTTON ,point.x,point.y ,this);
}
else
{
if(hItem != m_ParentItem && m_Tree.GetItemText(hItem) != theApp.m_skMainSocket.GetUserName() && theApp.m_skMainSocket.GetState() == HAVELOGIN)
{
HTREEITEM hParent = m_Tree.GetParentItem(hItem);
CString strRoom = m_Tree.GetItemText(hParent);
if(strRoom == theApp.m_skMainSocket.GetRoomName())
{
menu.LoadMenu(IDR_CLIENT);
pContextMenu = menu.GetSubMenu(0);
ClientToScreen(&point);
pContextMenu->TrackPopupMenu(TPM_LEFTBUTTON ,point.x,point.y ,this);
}
else
AfxMessageBox("处于不同的房间内,不能执行此项操作");
}
}
}
*pResult = 0;
}
extern CChatClientApp theApp;
void CMyTreeView::OnJoininroom()
{
// TODO: Add your command handler code here
Message msObj;
HTREEITEM hItem;
if(theApp.m_skMainSocket.GetState() == NOTLOGIN)
{
//构造msobj
hItem = m_Tree.GetSelectedItem();
CString strRoomName = m_Tree.GetItemText(hItem);
CString strUsrName = theApp.m_skMainSocket.GetUserName();
// theApp.m_skMainSocket.SetUserName(strUsrName);
theApp.m_skMainSocket.SetRoomName(strRoomName);
theApp.m_skMainSocket.SetState(HAVELOGIN);
msObj.iType = USERLOG;
msObj.iSubType = USERLOGIN;
int iLen = strRoomName.GetLength();
iLen > 20 ? 20: iLen;
lstrcpy(msObj.strRoom,_T(strRoomName.GetBuffer(iLen)));
strRoomName.ReleaseBuffer();
iLen = strUsrName.GetLength();
iLen > 20 ? 20 : iLen;
lstrcpy(msObj.strName,_T(strUsrName.GetBuffer(iLen)));
strUsrName.ReleaseBuffer();
iLen = theApp.m_skMainSocket.Send(&msObj,sizeof(msObj));
if(iLen < sizeof(msObj))
{
AfxMessageBox("发送失败");
return;
}
}
else
if(theApp.m_skMainSocket.GetState() == HAVELOGIN)
{
HTREEITEM hItem = m_Tree.GetSelectedItem();
CString strRoomName = m_Tree.GetItemText(hItem);
if(strRoomName != theApp.m_skMainSocket.GetRoomName())
{
HTREEITEM hItem = m_Tree.GetChildItem(m_ParentItem);
msObj.iType = USERSESSION;
msObj.iSubType = CHANGEROOM;
//用户名
CString strTemp;
strTemp = theApp.m_skMainSocket.GetUserName();
int iLen = strTemp.GetLength();
iLen > 20 ? 20:iLen;
lstrcpy(msObj.strName,_T(strTemp.GetBuffer(iLen)));
strTemp.ReleaseBuffer();
//旧房件名
strTemp = theApp.m_skMainSocket.GetRoomName();
iLen = strTemp.GetLength();
iLen > 20 ? 20 : iLen;
lstrcpy(msObj.strRoom,_T(strTemp.GetBuffer(iLen)));
strTemp.ReleaseBuffer();
//新房间名
hItem = m_Tree.GetSelectedItem();
strTemp = m_Tree.GetItemText(hItem);
iLen = strTemp.GetLength();
iLen > 20 ? 20 :iLen;
lstrcpy(msObj.strContent,_T(strTemp.GetBuffer(iLen)));
strTemp.ReleaseBuffer();
if(theApp.m_skMainSocket.Send(&msObj,sizeof(msObj)) != sizeof(msObj))
{
AfxMessageBox("发送错误");
}
theApp.m_skMainSocket.SetRoomName(m_Tree.GetItemText(hItem));
}
}
return;
}
void CMyTreeView::OnClientOut(Message wParam, LPARAM lParam)
{
Message msObj = wParam;
CString strRoom = msObj.strRoom;
CString strUsrName = msObj.strName;
HTREEITEM hItem = m_Tree.GetChildItem(m_ParentItem);
BOOL bFind = FALSE;
while(hItem && !bFind)
{
CString strNodeName = m_Tree.GetItemText(hItem);
if(strNodeName == strRoom)
{
//查找用户名的那一项
HTREEITEM hChildItem = m_Tree.GetChildItem(hItem);
while(hChildItem)
{
CString strUserNode = m_Tree.GetItemText(hChildItem);
if(strUserNode == strUsrName)
{
m_Tree.DeleteItem(hChildItem);
m_Tree.Expand(hItem,TVE_EXPAND);
bFind = TRUE;
break;
}
hChildItem = m_Tree.GetNextItem(hChildItem,1);
}
}
hItem = m_Tree.GetNextItem(hItem,1);
}
}
void CMyTreeView::OnNewClientIn(Message wParam, LPARAM lParam)
{
Message msObj = wParam;
CString strRoom = msObj.strRoom;
CString strUsrName = msObj.strName;
//自己加入的消息传入进来
if(strRoom == theApp.m_skMainSocket.GetRoomName() && strUsrName == theApp.m_skMainSocket.GetUserName())
{
//改变FormView中的数据
CClientFormView * m_pFormView =(CClientFormView *) ((CMainFrame * )AfxGetMainWnd())->GetFormView();
ASSERT(m_pFormView != NULL);
ASSERT_VALID(m_pFormView);
m_pFormView ->SetDlgItemText(IDC_SELFNAME,strUsrName);
m_pFormView ->SetDlgItemText(IDC_ROOMNAME,strRoom);
//改变任务栏图标的提醒信息
lstrcpy(theApp.TaskIcon.szTip,_T(strUsrName.GetBuffer(strUsrName.GetLength())));
Shell_NotifyIcon(NIM_MODIFY,&theApp.TaskIcon);
//显示正常的窗口
return;
}
HTREEITEM hItem = m_Tree.GetChildItem(m_ParentItem);
while(hItem)
{
CString strNodeName = m_Tree.GetItemText(hItem);
CString strTemp = theApp.m_skMainSocket.GetUserName();
if(strNodeName == strRoom)
{
if(strUsrName != strTemp)
{
m_Tree.InsertItem(strUsrName,0,1,hItem);
m_Tree.Expand(hItem,TVE_EXPAND);
break;
}
}
hItem = m_Tree.GetNextItem(hItem,1);
}
}
void CMyTreeView::OnMenuSend()
{
// TODO: Add your command handler code here
CSendMessageDlg Dlg;
if(Dlg.DoModal() == IDOK)
{
if(Dlg.m_strSentence.GetLength())
{
if(Dlg.m_strSentence.GetLength == 0)
return;
Message msObj;
memset(&msObj,0,sizeof(Message));
msObj.iType = USERSESSION;
msObj.iSubType = SAYINPRIVATE;
CString strTemp = theApp.m_skMainSocket.GetRoomName();
int iLen = strTemp.GetLength();
lstrcpy(msObj.strRoom,_T(strTemp.GetBuffer(iLen)));
strTemp.ReleaseBuffer();
strTemp = Dlg.m_strSentence;
iLen = strTemp.GetLength();
iLen > 1024 ? 1024 : iLen;
lstrcpy(msObj.strContent,_T(strTemp.GetBuffer(iLen)));
strTemp.ReleaseBuffer();
//自己的名字
strTemp = theApp.m_skMainSocket.GetUserName();
iLen = strTemp.GetLength();
iLen > 20 ? 20:iLen;
lstrcpy(msObj.strName,_T(strTemp.GetBuffer(iLen)));
strTemp.ReleaseBuffer();
//说话对象的名字
HTREEITEM hItem = m_Tree.GetSelectedItem();
strTemp = m_Tree.GetItemText(hItem);
iLen = strTemp.GetLength();
iLen > 20 ? 20 : iLen;
lstrcpy(msObj.strClientName,_T(strTemp.GetBuffer(iLen)));
strTemp.ReleaseBuffer();
iLen = theApp.m_skMainSocket.Send(&msObj,sizeof(Message));
}
}
return;
}
//接收到信息
//整个的处理过程是这样:
//首先,接收到信息以后,在m_ClientNameList中添加一项,这样,在ontimer中,可以检查链表中都是有谁在发送信息,而且
//你还没有回复.这样OnTimer中就可以实现多个人的头像一起晃动。
//当你回复或者取消以后,相应的应该在m_ClientNameList中删除已经恢复或者取消的那一项。
void CMyTreeView::OnSayInPrivate(Message wParam,LPARAM lParam)
{
Message msObj = wParam;
CString strClientName = msObj.strName;
Client * pNewClient;
//设置每一个Client对应的ontimer中IDEVENT
pNewClient = new Client();
int iCount = m_ClientNameList.GetCount();
pNewClient ->SetUserName(strClientName);
int iMaxId = 1;
if(iCount == 0)
{
pNewClient ->SetTimerId(iMaxId);
}
else
{
//查找出最大的iTimerId;
POSITION pos;
pos = m_ClientNameList.GetHeadPosition();
if(pos)
{
for(int i = 0; i< iCount; i ++)
{
Client * pTempClient = (Client *)m_ClientNameList.GetNext(pos);
if(iMaxId > pTempClient ->GetTimerId())
iMaxId = pTempClient ->GetTimerId();
}
iMaxId ++;
}
pNewClient ->SetTimerId(iMaxId);
}
m_ClientNameList.AddTail(pNewClient);
//启动Ontimer
SetTimer(iMaxId,800,NULL);
//显示对话框
CString strContent = msObj.strContent;
CShowMessage Dlg(strContent,strClientName,iMaxId);
Dlg.DoModal();
SetIcon(strClientName,0,1);
////
return;
}
BOOL CMyTreeView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Add your specialized code here and/or call the base class
cs.style |= TVS_HASLINES;
cs.style |= TVS_LINESATROOT;
cs.style |= TVS_HASBUTTONS;
return CTreeView::PreCreateWindow(cs);
}
//启动ONtimer。主要是让用户的图标晃动,并且发出报警的声音
void CMyTreeView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
POSITION pos;
pos = m_ClientNameList.GetHeadPosition();
int iCount = m_ClientNameList.GetCount();
if(pos)
{
for(int i = 0 ;i < iCount; i++)
{
Client * pTempClient =(Client *) m_ClientNameList.GetNext(pos);
if(nIDEvent ==(UINT) pTempClient->GetTimerId())
{
int i = pTempClient ->GetTimes();
pTempClient->AddTimes();
i %= 2;
if(i == 1)
{
theApp.TaskIcon.hIcon = theApp.LoadIcon(IDI_EMPTY);
Shell_NotifyIcon(NIM_MODIFY,&theApp.TaskIcon);
PlaySound("msg.wav",NULL,SND_ASYNC);
SetIcon(pTempClient ->GetUserName(),0,0);
}
else
{
theApp.TaskIcon.hIcon = theApp.LoadIcon(IDI_TASKICON);
Shell_NotifyIcon(NIM_MODIFY,&theApp.TaskIcon);
SetIcon(pTempClient ->GetUserName(),5,5);
}
}//end if IDEvent ==
}//endfor
}//end if pos
CTreeView::OnTimer(nIDEvent);
}
//在创建的链表中删除一项
void CMyTreeView::DeleteOneClient(const CString & strName,const int iID)
{
POSITION pos;
pos = m_ClientNameList.GetHeadPosition();
int iCount = m_ClientNameList.GetCount();
POSITION tempos = pos;
if(pos && iCount)
{
for(int i = 0;i < iCount; i ++)
{
tempos = pos;
Client * pTempClient = (Client *)m_ClientNameList.GetNext(pos);
if(pTempClient->GetUserName() == strName && pTempClient->GetTimerId() == iID)
{
delete pTempClient;
m_ClientNameList.RemoveAt(tempos);
break;
}
}
}
return;
}
//设置树型控件中某一项的图标
void CMyTreeView::SetIcon(const CString &strClientName,const int iNormalIcon,const int iSelectedIcon)
{
CString strRoom;
strRoom = theApp.m_skMainSocket.GetRoomName();
HTREEITEM hItem = m_Tree.GetChildItem(m_ParentItem);
BOOL bFind = FALSE;
while(hItem && !bFind)
{
CString strNodeName = m_Tree.GetItemText(hItem);
if(strNodeName == strRoom)
{
//查找用户名的那一项
HTREEITEM hChildItem = m_Tree.GetChildItem(hItem);
while(hChildItem)
{
CString strUserNode = m_Tree.GetItemText(hChildItem);
if(strUserNode == strClientName)
{
m_Tree.SetItemImage(hChildItem,iNormalIcon,iSelectedIcon);
}
hChildItem = m_Tree.GetNextItem(hChildItem,1);
}
}
hItem = m_Tree.GetNextItem(hItem,1);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -