// FriendDlg.cpp : 实现文件 // #include "stdafx.h" #include "IRC_UI.h" #include "FriendDlg.h" #include "IRC_UIDlg.h" // CFriendDlg 对话框 IMPLEMENT_DYNAMIC(CFriendDlg, CDialog) CFriendDlg::CFriendDlg(CWnd* pParent /*=NULL*/) : CDialog(CFriendDlg::IDD, pParent) { m_GroupInfoMap.clear(); m_FriendInfoMap.clear(); } CFriendDlg::~CFriendDlg() { for (map::iterator IteGroup = m_GroupInfoMap.begin(); IteGroup != m_GroupInfoMap.end(); IteGroup++) { delete IteGroup->second; } m_GroupInfoMap.clear(); for (map::iterator IteFriend = m_FriendInfoMap.begin(); IteFriend != m_FriendInfoMap.end(); IteFriend++) { delete IteFriend->second; } m_FriendInfoMap.clear(); } void CFriendDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_GROUPINFO, m_GroupInfo); DDX_Control(pDX, IDC_FRIENDINFO, m_FriendInfo); } BEGIN_MESSAGE_MAP(CFriendDlg, CDialog) ON_COMMAND(ID_FRIENDS_DETAILS, &CFriendDlg::OnFriendsDetails) ON_UPDATE_COMMAND_UI(ID_FRIENDS_DETAILS, &CFriendDlg::OnUpdateFriendsDetails) ON_COMMAND(ID_FRIENDS_PRICHAT, &CFriendDlg::OnFriendsPrichat) ON_UPDATE_COMMAND_UI(ID_FRIENDS_PRICHAT, &CFriendDlg::OnUpdateFriendsPrichat) ON_COMMAND(ID_FRIENDS_COPYNAME, &CFriendDlg::OnFriendsCopyname) ON_UPDATE_COMMAND_UI(ID_FRIENDS_COPYNAME, &CFriendDlg::OnUpdateFriendsCopyname) ON_NOTIFY(NM_RCLICK, IDC_FRIENDINFO, &CFriendDlg::OnNMRclickFriendinfo) ON_NOTIFY(NM_CLICK, IDC_GROUPINFO, &CFriendDlg::OnNMClickGroupinfo) ON_NOTIFY(NM_CUSTOMDRAW, IDC_FRIENDINFO, &CFriendDlg::OnNMCustomdrawFriendinfo) ON_NOTIFY(HDN_ITEMCLICK, 0, &CFriendDlg::OnHdnItemclickFriendinfo) ON_NOTIFY(NM_DBLCLK, IDC_FRIENDINFO, &CFriendDlg::OnNMDblclkFriendinfo) END_MESSAGE_MAP() // CFriendDlg 消息处理程序 BOOL CFriendDlg::OnInitDialog() { CDialog::OnInitDialog(); m_UsrInfoDlg = NULL; CIRC_UIDlg* pIrcMain = static_cast(AfxGetApp()->m_pMainWnd); BITMAP BitMap; pIrcMain->m_IrcFlag.GetBitmap(&BitMap); m_ImgList.Create(BitMap.bmWidth, BitMap.bmHeight, ILC_COLORDDB | ILC_MASK, 1, 1); m_ImgList.Add(&pIrcMain->m_IrcFlag, (CBitmap*)NULL); m_BmpSortDown.LoadBitmap(IDB_BMP_SORTDOWN); m_BmpSortUp.LoadBitmap(IDB_BMP_SORTUP); m_SortImgList.Create(44, 44, ILC_COLORDDB | ILC_MASK, 2, 1); m_SortImgList.Add(&m_BmpSortUp, (CBitmap*)NULL); m_SortImgList.Add(&m_BmpSortDown, (CBitmap*)NULL); m_CurPosFriend = NULL; m_SortType = -1; InitFriendInfo(); m_FriendInfo.SetImageList(&m_ImgList, LVSIL_SMALL); //m_FriendInfo.GetHeaderCtrl()->SetImageList(&m_SortImgList); m_FriendMenu.LoadMenu(IDR_FRIENDS); return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE } void CFriendDlg::InitFriendInfo() { CRect rectGroup; m_GroupInfo.GetClientRect(&rectGroup); m_GroupInfo.InsertColumn(0, _T(""), LVCFMT_LEFT, rectGroup.Width()); ListView_SetExtendedListViewStyle(m_GroupInfo.m_hWnd, LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_GRIDLINES); /* LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); lf.lfHeight = 4; strcpy(lf.lfFaceName, "宋体"); CFont font; font.CreateFontIndirect(&lf); m_GroupInfo.SetFont(&font, TRUE); */ CRect rectFriendInfo; m_FriendInfo.GetClientRect(&rectFriendInfo); int nColWidth = rectFriendInfo.Width() / 4; m_FriendInfo.InsertColumn(0, _T("姓名"), LVCFMT_CENTER, nColWidth); m_FriendInfo.InsertColumn(1, _T("职业"), LVCFMT_CENTER, nColWidth); m_FriendInfo.InsertColumn(2, _T("种族"), LVCFMT_CENTER, nColWidth); m_FriendInfo.InsertColumn(3, _T("性别"), LVCFMT_CENTER, nColWidth); ListView_SetExtendedListViewStyle(m_FriendInfo.m_hWnd, LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_GRIDLINES); } void CFriendDlg::AddFriendInfo(FriendInfo_I* pFriendInfo) { bool bNewFriend = false; map::iterator IteFriendInfo = m_FriendInfoMap.find(pFriendInfo->friendID); if (IteFriendInfo == m_FriendInfoMap.end()) { FriendInfo_I* pNewFriendInfo = new FriendInfo_I; memcpy(pNewFriendInfo, pFriendInfo, sizeof(FriendInfo_I)); m_FriendInfoMap[pFriendInfo->friendID] = pNewFriendInfo; bNewFriend = true; } else { if (((FriendInfo_I*)IteFriendInfo->second)->isOnline == pFriendInfo->isOnline) { return; } ((FriendInfo_I*)IteFriendInfo->second)->isOnline = pFriendInfo->isOnline; } map::iterator IteGroupInfo = m_GroupInfoMap.find(pFriendInfo->groupID); if (IteGroupInfo != m_GroupInfoMap.end()) { DispGroupInfo* pDispGroupInfo = IteGroupInfo->second; if (bNewFriend) { pDispGroupInfo->FriendsCount++; } if (pFriendInfo->isOnline != 0) { pDispGroupInfo->FriendCountOnLine++; } LVFINDINFO info; info.flags = LVFI_STRING | LVFI_PARTIAL; info.psz = pDispGroupInfo->GroupInfo.m_GroupName; int nIndex = m_GroupInfo.FindItem(&info); if (nIndex != -1) { CString strItem; strItem.Format(_T("%s %d / %d"), pDispGroupInfo->GroupInfo.m_GroupName, pDispGroupInfo->FriendCountOnLine, pDispGroupInfo->FriendsCount); m_GroupInfo.SetItemText(nIndex, 0, strItem); } } } void CFriendDlg::OnFriendsDetails() { if (m_UsrInfoDlg != NULL) { m_UsrInfoDlg->DestroyWindow(); } m_UsrInfoDlg = new CUsrInfoDlg(this); m_UsrInfoDlg->Create(CUsrInfoDlg::IDD, this); m_UsrInfoDlg->SetParentInfo(1, this); CRect rectUsrInfo; m_UsrInfoDlg->GetWindowRect(&rectUsrInfo); CPoint pnt; GetCursorPos(&pnt); m_UsrInfoDlg->MoveWindow(pnt.x, pnt.y, rectUsrInfo.Width(), rectUsrInfo.Height()); m_UsrInfoDlg->UpdateUsrInfo(m_CurPosFriend); m_UsrInfoDlg->ShowWindow(SW_SHOW); } void CFriendDlg::OnUpdateFriendsDetails(CCmdUI *pCmdUI) { } void CFriendDlg::OnFriendsPrichat() { if (m_CurPosFriend == NULL) { return; } CIRC_UIDlg* pIrcMain = static_cast(AfxGetApp()->m_pMainWnd); pIrcMain->NewPrivateChat(m_CurPosFriend->nickName); } void CFriendDlg::OnUpdateFriendsPrichat(CCmdUI *pCmdUI) { pCmdUI->Enable(m_CurPosFriend->isOnline != 0); } void CFriendDlg::OnFriendsCopyname() { if (OpenClipboard()) { HGLOBAL hClipBuffer; char* pBuffer; EmptyClipboard(); hClipBuffer = GlobalAlloc(GMEM_DDESHARE, strlen(m_CurPosFriend->nickName) + 1); pBuffer = (char*)GlobalLock(hClipBuffer); strcpy(pBuffer, m_CurPosFriend->nickName); GlobalUnlock(hClipBuffer); SetClipboardData(CF_TEXT, hClipBuffer); CloseClipboard(); } } void CFriendDlg::OnUpdateFriendsCopyname(CCmdUI *pCmdUI) { } void CFriendDlg::OnNMRclickFriendinfo(NMHDR *pNMHDR, LRESULT *pResult) { CMenu* pMenu = m_FriendMenu.GetSubMenu(0); CPoint point; GetCursorPos(&point); m_FriendInfo.ScreenToClient(&point); LVHITTESTINFO lvinfo; lvinfo.pt = point; lvinfo.flags = LVHT_ABOVE; int nIndex = m_FriendInfo.SubItemHitTest(&lvinfo); if (nIndex != -1) { m_CurPosFriend = reinterpret_cast(m_FriendInfo.GetItemData(nIndex)); m_FriendInfo.ClientToScreen(&point); if (m_CurPosFriend->isOnline == 0) { pMenu->EnableMenuItem(ID_FRIENDS_PRICHAT, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); } else { pMenu->EnableMenuItem(ID_FRIENDS_PRICHAT, MF_BYCOMMAND | MF_ENABLED); } pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this); } else { m_CurPosFriend = NULL; } *pResult = 0; } void CFriendDlg::AddFriendGroupInfo(FriendGroupInfo_I* pFriendGroupInfo) { DispGroupInfo* pDispGroupInfo = NULL; map::iterator IteGroup = m_GroupInfoMap.find(pFriendGroupInfo->m_GroupID); if (IteGroup != m_GroupInfoMap.end()) { pDispGroupInfo = IteGroup->second; pDispGroupInfo->FriendCountOnLine = 0; return; } pDispGroupInfo = new DispGroupInfo; memcpy(&pDispGroupInfo->GroupInfo, pFriendGroupInfo, sizeof(FriendGroupInfo_I)); pDispGroupInfo->FriendsCount = 0; pDispGroupInfo->FriendCountOnLine = 0; m_GroupInfoMap[pDispGroupInfo->GroupInfo.m_GroupID] = pDispGroupInfo; int nItemCount = m_GroupInfo.GetItemCount(); CString strItem; strItem.Format(_T("%s %d / %d"), pDispGroupInfo->GroupInfo.m_GroupName, pDispGroupInfo->FriendCountOnLine, pDispGroupInfo->FriendsCount); int nIndex = m_GroupInfo.InsertItem(nItemCount, strItem); m_GroupInfo.SetItemData(nIndex, (DWORD_PTR)pDispGroupInfo); } void CFriendDlg::OnNMClickGroupinfo(NMHDR *pNMHDR, LRESULT *pResult) { CPoint point; GetCursorPos(&point); m_GroupInfo.ScreenToClient(&point); LVHITTESTINFO lvinfo; lvinfo.pt = point; lvinfo.flags = LVHT_ABOVE; int nIndex = m_GroupInfo.SubItemHitTest(&lvinfo); if (nIndex != -1) { DispGroupInfo* pDispGroupInfo = reinterpret_cast(m_GroupInfo.GetItemData(nIndex)); if (pDispGroupInfo) { DisplayFriendInfo(pDispGroupInfo->GroupInfo.m_GroupID); } } *pResult = 0; } void CFriendDlg::DisplayFriendInfo(unsigned long ulGroupID) { m_FriendInfo.SetRedraw(FALSE); m_FriendInfo.DeleteAllItems(); for (map::iterator Ite = m_FriendInfoMap.begin(); Ite != m_FriendInfoMap.end(); Ite++) { FriendInfo_I* pFriendInfo = Ite->second; if (pFriendInfo->groupID == ulGroupID) { int nItemCount = m_FriendInfo.GetItemCount(); int nIndex; if (pFriendInfo->isOnline == 2) { nIndex = m_FriendInfo.InsertItem(nItemCount, pFriendInfo->nickName, 0); } else { nIndex = m_FriendInfo.InsertItem(nItemCount, pFriendInfo->nickName, -1); } CIRC_UIDlg* pIrcMain = reinterpret_cast(AfxGetApp()->m_pMainWnd); m_FriendInfo.SetItemText(nIndex, 1, pIrcMain->GetIrcInfo()->GetClassByClassID(pFriendInfo->playerClass).c_str()); m_FriendInfo.SetItemText(nIndex, 2, pIrcMain->GetIrcInfo()->GetRaceByRaceID(pFriendInfo->playerRace).c_str()); m_FriendInfo.SetItemText(nIndex, 3, pIrcMain->GetIrcInfo()->GetGender(pFriendInfo->playerSex).c_str()); m_FriendInfo.SetItemData(nIndex, (DWORD_PTR)pFriendInfo); } } m_FriendInfo.SortItems(FriendInfoSort, (DWORD_PTR)-1); m_FriendInfo.SetRedraw(TRUE); m_FriendInfo.Invalidate(); m_FriendInfo.UpdateWindow(); } void CFriendDlg::FriendInfoUpdate(FriendInfo_I* pFriendInfo) { map::iterator IteFriendInfo = m_FriendInfoMap.find(pFriendInfo->friendID); if (IteFriendInfo != m_FriendInfoMap.end()) { IteFriendInfo->second->isOnline = pFriendInfo->isOnline; IteFriendInfo->second->playerLevel = pFriendInfo->playerLevel; strncpy(IteFriendInfo->second->GuildName, pFriendInfo->GuildName, strlen(pFriendInfo->GuildName)); strncpy(IteFriendInfo->second->FereName, pFriendInfo->FereName, strlen(pFriendInfo->FereName)); //更新好友列表的在线状态信息 map::iterator IteGroupInfo = m_GroupInfoMap.find(IteFriendInfo->second->groupID); if (IteGroupInfo != m_GroupInfoMap.end()) { DispGroupInfo* pDispGroupInfo = IteGroupInfo->second; if (pFriendInfo->isOnline != 0) { if (pDispGroupInfo->FriendsCount > pDispGroupInfo->FriendCountOnLine) { pDispGroupInfo->FriendCountOnLine++; } } else { if (pDispGroupInfo->FriendCountOnLine > 0) { pDispGroupInfo->FriendCountOnLine--; } } LVFINDINFO info; info.flags = LVFI_STRING | LVFI_PARTIAL; info.psz = pDispGroupInfo->GroupInfo.m_GroupName; int nIndex = m_GroupInfo.FindItem(&info); if (nIndex != -1) { CString strItem; strItem.Format(_T("%s %d / %d"), pDispGroupInfo->GroupInfo.m_GroupName, pDispGroupInfo->FriendCountOnLine, pDispGroupInfo->FriendsCount); m_GroupInfo.SetItemText(nIndex, 0, strItem); } } //更新好友项的状态 LVFINDINFO info; info.flags = LVFI_STRING | LVFI_PARTIAL; FriendInfo_I* pFriendInfo = IteFriendInfo->second; info.psz = pFriendInfo->nickName; int nIndex = m_FriendInfo.FindItem(&info); if (nIndex != -1) { LVITEM lvItem; ZeroMemory(&lvItem, sizeof(LVITEM)); lvItem.iItem = nIndex; lvItem.mask = LVIF_IMAGE; lvItem.iImage = pFriendInfo->isOnline == 2 ? 0 : -1; m_FriendInfo.SetItem(&lvItem); if (m_SortType == -1) { m_FriendInfo.SortItems(FriendInfoSort, -1); } } } } int CFriendDlg::GetFriendOnLineType(unsigned long ulFriendID) { int nOnLineType = -1; map::iterator Ite = m_FriendInfoMap.find(ulFriendID); if (Ite != m_FriendInfoMap.end()) { nOnLineType = Ite->second->isOnline; } return nOnLineType; } CString CFriendDlg::GetFriendName(unsigned long ulFriendID) { map::iterator IteFriendInfo = m_FriendInfoMap.find(ulFriendID); if (IteFriendInfo != m_FriendInfoMap.end()) { return IteFriendInfo->second->nickName; } else return _T(""); } bool CFriendDlg::IsFriend(const string& strRoleName) { bool bRet = false; for (map::iterator Ite = m_FriendInfoMap.begin(); Ite != m_FriendInfoMap.end(); Ite++) { if (strRoleName == Ite->second->nickName) { bRet = true; break; } } return bRet; } void CFriendDlg::OnNMCustomdrawFriendinfo(NMHDR *pNMHDR, LRESULT *pResult) { //LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); *pResult = CDRF_DODEFAULT; LPNMLVCUSTOMDRAW pLvNMCD = reinterpret_cast(pNMHDR); switch(pLvNMCD->nmcd.dwDrawStage) { case CDDS_PREPAINT: { *pResult = CDRF_NOTIFYITEMDRAW; } break; case CDDS_ITEMPREPAINT: { *pResult = CDRF_NOTIFYSUBITEMDRAW; } break; case CDDS_ITEMPREPAINT | CDDS_SUBITEM: { int nItem = static_cast(pLvNMCD->nmcd.dwItemSpec); COLORREF clrTextColr; FriendInfo_I* pFriendInfo = reinterpret_cast(m_FriendInfo.GetItemData(nItem)); if (pFriendInfo->isOnline == 0) { clrTextColr = RGB(222,222,222); //clrBkColor = RGB(255, 255, 0); } else { clrTextColr = RGB(0, 0, 0); //clrBkColor = RGB(255, 255, 255); } pLvNMCD->clrText = clrTextColr; //pLvNMCD->clrTextBk = clrBkColor; } break; default: break; } } void CFriendDlg::OnHdnItemclickFriendinfo(NMHDR *pNMHDR, LRESULT *pResult) { LPNMHEADER phdr = reinterpret_cast(pNMHDR); //排序图标 /* CHeaderCtrl* pHeaderCtrl = m_FriendInfo.GetHeaderCtrl(); HDITEM hdItem; hdItem.mask = HDI_FORMAT | HDI_IMAGE; BOOL bRet = pHeaderCtrl->GetItem(phdr->iItem, &hdItem); */ int nColIndex = m_SortType / 2; if (nColIndex != phdr->iItem) { m_SortType = phdr->iItem * 2; } else { m_SortType = m_SortType == nColIndex * 2 ? ++m_SortType : --m_SortType; } m_FriendInfo.SortItems(FriendInfoSort, (DWORD_PTR)m_SortType); *pResult = 0; } int CALLBACK CFriendDlg::FriendInfoSort(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { int nSortType = (int)lParamSort; FriendInfo_I* pFriendInfo1 = reinterpret_cast(lParam1); FriendInfo_I* pFriendInfo2 = reinterpret_cast(lParam2); int nResult = 0; CIRC_UIDlg* pIrcMain = reinterpret_cast(AfxGetApp()->m_pMainWnd); switch(nSortType) { case -1: { nResult = pFriendInfo2->isOnline - pFriendInfo1->isOnline; if (nResult == 0) { nResult = pFriendInfo1->joinID - pFriendInfo2->joinID; } } break; case 0: { nResult = strcmp(pFriendInfo1->nickName, pFriendInfo2->nickName); } break; case 1: { nResult = strcmp(pFriendInfo2->nickName, pFriendInfo1->nickName); } break; case 2: { nResult = strcmp(pIrcMain->GetIrcInfo()->GetClassByClassID(pFriendInfo1->playerClass).c_str(), pIrcMain->GetIrcInfo()->GetClassByClassID(pFriendInfo2->playerClass).c_str()); } break; case 3: { nResult = -(strcmp(pIrcMain->GetIrcInfo()->GetClassByClassID(pFriendInfo1->playerClass).c_str(), pIrcMain->GetIrcInfo()->GetClassByClassID(pFriendInfo2->playerClass).c_str())); } break; case 4: { nResult = strcmp(pIrcMain->GetIrcInfo()->GetRaceByRaceID(pFriendInfo1->playerRace).c_str(), pIrcMain->GetIrcInfo()->GetRaceByRaceID(pFriendInfo2->playerRace).c_str()); } break; case 5: { nResult = -(strcmp(pIrcMain->GetIrcInfo()->GetRaceByRaceID(pFriendInfo1->playerRace).c_str(), pIrcMain->GetIrcInfo()->GetRaceByRaceID(pFriendInfo2->playerRace).c_str())); } break; case 6: { nResult = pFriendInfo1->playerSex - pFriendInfo2->playerSex; } break; case 7: { nResult = pFriendInfo2->playerSex - pFriendInfo1->playerSex; } default: break; } return nResult; } void CFriendDlg::OnNMDblclkFriendinfo(NMHDR *pNMHDR, LRESULT *pResult) { CPoint point; GetCursorPos(&point); m_FriendInfo.ScreenToClient(&point); LVHITTESTINFO lvinfo; lvinfo.pt = point; lvinfo.flags = LVHT_ABOVE; int nIndex = m_FriendInfo.SubItemHitTest(&lvinfo); if (nIndex != -1) { m_CurPosFriend = reinterpret_cast(m_FriendInfo.GetItemData(nIndex)); if (m_CurPosFriend->isOnline != 0) OnFriendsPrichat(); } else { m_CurPosFriend = NULL; } *pResult = 0; } void CFriendDlg::ClearFriendInfo() { m_FriendInfo.DeleteAllItems(); m_GroupInfo.DeleteAllItems(); m_CurPosFriend = NULL; m_SortType = -1; for (map::iterator Ite = m_GroupInfoMap.begin(); Ite != m_GroupInfoMap.end(); Ite++) { delete Ite->second; } m_GroupInfoMap.clear(); for (map::iterator Ite = m_FriendInfoMap.begin(); Ite != m_FriendInfoMap.end(); Ite++) { delete Ite->second; } m_FriendInfoMap.clear(); } void CFriendDlg::OffLine() { for (map::iterator Ite = m_FriendInfoMap.begin(); Ite != m_FriendInfoMap.end(); Ite++) { FriendInfo_I* pFriendInfo = Ite->second; pFriendInfo->isOnline = 0; FriendInfoUpdate(pFriendInfo); } }