📄 contactview.cpp
字号:
// ContactView.cpp : implementation file
//
#include "stdafx.h"
#include "Netmsg.h"
#include "ContactView.h"
#include "NetSocket.h"
#include "NewContact.h"
#include "MainFrm.h"
#include "NetmsgView.h"
#include "Conversation.h"
#include "NotifyThread.h"
#include "ConversationThread.h"
#include "PopWndThread.h"
#include "SoundThread.h"
#include "FileSend.h"
#include "TransferStatus.h"
#include "ListenSocket.h"
#include <direct.h>
#include <mmsystem.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//The main list view of this program
CContactView::CContactView()
{
Notify = NULL;
Load = 0;
LastPopup = NULL;
bmConvBack = (HBITMAP)::LoadImage(0, "convback.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
}
CContactView::~CContactView()
{
delete ButtonImageList;
delete ListenSocket;
}
BEGIN_MESSAGE_MAP(CContactView, CListCtrl)
//{{AFX_MSG_MAP(CContactView)
ON_WM_RBUTTONDOWN()
ON_WM_CLOSE()
ON_WM_LBUTTONDBLCLK()
ON_WM_DROPFILES()
ON_WM_CREATE()
ON_WM_TIMER()
ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
ON_MESSAGE(WM_SENDTHISMESSAGE, OnSendMessage)
ON_MESSAGE(WM_SOCKCONNECT, OnSockConnect)
ON_MESSAGE(WM_DESTROYME, OnDestroyThread)
ON_MESSAGE(WM_BLOCKTHISCONTACT, OnBlockContact)
ON_MESSAGE(WM_TYPENOTIFY, OnTypeNotify)
ON_MESSAGE(WM_REQUESTXFER, OnRequestSend)
ON_MESSAGE(WM_CANCELXFER, OnCancelSend)
ON_MESSAGE(WM_TRANSFERCOMPLETE, OnTransferComplete)
ON_MESSAGE(WM_UPDATEMYFONT, OnUpdateFont)
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomdraw)
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CContactView message handlers
BOOL CContactView::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
return CListCtrl::Create(dwStyle, rect, pParentWnd, nID);
}
int CContactView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CListCtrl::OnCreate(lpCreateStruct) == -1)
return -1;
GetApp()->View = this;
CBitmap *OnlineBmp, *OfflineBmp, *Blocked, *Away;
ButtonImageList = new CImageList();
OnlineBmp = new CBitmap();
OfflineBmp = new CBitmap();
Blocked = new CBitmap();
Away = new CBitmap();
OnlineBmp->LoadBitmap(IDB_ONLINE);
OfflineBmp->LoadBitmap(IDB_OFFLINE);
Blocked->LoadBitmap(IDB_BLOCKED);
Away->LoadBitmap(IDB_AWAY);
ButtonImageList->Create(16, 16, ILC_COLOR16, 2, 2);
ButtonImageList->Add(OnlineBmp, RGB(0, 0, 0));
ButtonImageList->Add(OfflineBmp, RGB(0, 0, 0));
ButtonImageList->Add(Blocked, RGB(0, 0, 0));
ButtonImageList->Add(Away, RGB(0, 0, 0));
SetImageList(ButtonImageList, LVSIL_SMALL);
ShowIps = AfxGetApp()->GetProfileInt("Settings", "ShowIps", 0) ? true : false;
DragAcceptFiles(TRUE);
LoadPlugins();
LoadContacts();
char buf[2048];
strcpy(buf, cwd);
strcat(buf, "\\back.bmp");
SetBkImage(buf, FALSE, 100, 100);
Me.Flags &= ~CFL_OFFLINE;
USERFONT *uf;
unsigned int sz = sizeof(USERFONT);
if (!AfxGetApp()->GetProfileBinary("Settings", "MyFont", (LPBYTE *)&uf, &sz))
{
uf = new USERFONT;
GetFont()->GetLogFont(&uf->lfFont);
uf->crColor = RGB(0, 0, 0);
uf->nPointSize = 100;
}
memcpy(&Me.uFont, uf, sizeof(USERFONT));
delete [] uf;
ListenSocket = new CListenSocket();
if (!ListenSocket->Create(8400))
{
MessageBox("Unable to bind to port 8400, ensure program is not already running", "Error", MB_OK|MB_ICONSTOP);
exit(1);
}
ListenSocket->Listen();
NotifyOthers();
delete OnlineBmp;
delete OfflineBmp;
delete Blocked;
delete Away;
LOGFONT lf;
GetFont()->GetLogFont(&lf);
lf.lfWeight = FW_BOLD;
FontBold.CreateFontIndirect(&lf);
LoadEmoticons();
return 0;
}
CContact *CContactView::AddContact(IP HostName)
{
if (GetContact(HostName))
return GetContact(HostName);
CContact *Contact = new CContact();
List.AddTail(Contact);
Contact->SetScreenName("Unknown User");
Contact->SetHost(HostName);
CNetSocket *NewSock = new CNetSocket(Contact);
BuildList();
if (!NewSock->Open())
{
delete NewSock;
Contact->SetSock(NULL);
MessageBox("Failed to connect to the machine with this address. Connection will retry at a later time",
"Failed to connect", MB_OK|MB_ICONWARNING);
}
else
{
Contact->SetSock(NewSock);
}
PluginsContactAdded(Contact);
return Contact;
}
void CContactView::SetOnline(IP HostName, CNetSocket *ClientSocket)
{
CContact *Contact = GetContact(HostName);
if (!IsSocket(ClientSocket))
return;
if (!Contact)
{
Contact = new CContact();
List.AddTail(Contact);
Contact->SetSock(ClientSocket);
Contact->GetSock()->Contact = Contact;
Contact->SetScreenName("Unknown User");
Contact->SetHost(HostName);
GetContact(HostName)->Flags |= CFL_AUTHENTICATE_NO;
SetOnline(HostName, ClientSocket);
PluginsContactAdded(Contact);
return;
}
else if (Contact && !(Contact->IsBlocked()) && !(Contact->Flags & CFL_AUTHENTICATE_NO) &&
!(Me.IsOffline()))
{
Contact->SetSock(ClientSocket);
::SendMyOnline(Contact);
}
else if (Contact && (Contact->IsBlocked()) && !(Contact->Flags & CFL_AUTHENTICATE_NO) &&
!(Me.IsOffline()))
{
Contact->SetSock(ClientSocket);
}
PluginsContactStatusChanged(Contact, CT_ONLINE);
}
bool CContactView::DeleteContact(CContact *Contact)
{
if (!IsContact(Contact))
return false;
if (Contact->IsConvWindowOpen())
{
MessageBox("You cannot delete a contact with a conversation window open.", "Delete contact", MB_OK|MB_ICONSTOP);
return false;
}
if (Notify)
if (Notify->Contact == Contact)
{
MessageBox("The program is currently trying to connect to this contact, you cannot delete it right now.", "Delete contact", MB_OK|MB_ICONSTOP);
return false;
}
PluginsContactDeleted(Contact);
List.RemoveAt(List.Find(Contact));
if (IsSocket(Contact->GetSock()))
{
Contact->GetSock()->Close();
delete Contact->GetSock();
Contact->SetSock(NULL);
}
delete Contact;
BuildList();
return true;
}
CContact *CContactView::GetContact(IP HostName)
{
POSITION pos;
pos = List.GetHeadPosition();
while (pos)
{
CContact *Contact = List.GetNext(pos);
if (Contact->GetHostName() == HostName)
return Contact;
}
return NULL;
}
CContact *CContactView::GetFromListItem(int item)
{
POSITION pos;
pos = List.GetHeadPosition();
while (pos)
{
CContact *Contact = List.GetNext(pos);
if (Contact->ListItem == item)
return Contact;
}
return NULL;
}
void CContactView::BuildList()
{
DeleteAllItems();
int Current = 1, Count = 0;
char buf[128];
int Icon = 0;
if (Me.IsAway())
Icon = 3;
if (Me.IsOffline())
Icon = 1;
sprintf(buf, "%s%s%s%s%s%s%s%s%s",
Me.GetScreenName(),
Me.IsAway() ? " " : "",
Me.IsAway() ? "(" : "",
Me.IsAway() ? Me.GetAwayReason() : "",
Me.IsAway() ? ")" : "",
Me.IsOffline() ? " " : "",
Me.IsOffline() ? "(" : "",
Me.IsOffline() ? "Appear Offline" : "",
Me.IsOffline() ? ")" : "");
InsertItem(0, buf, Icon);
POSITION pos;
pos = List.GetHeadPosition();
while (pos)
{
CContact *Contact = List.GetNext(pos);
if (Contact->IsOnline())
Count++;
}
sprintf(buf, "Online (%d)", Count);
InsertItem(1, buf, -1);
pos = List.GetHeadPosition();
while (pos)
{
CContact *Contact = List.GetNext(pos);
if (Contact->IsOnline())
{
char buf[512];
int Icon = 0;
if (Contact->IsAway())
Icon = 3;
if (Contact->IsBlocked())
Icon = 2;
sprintf(buf, "%s %s%s%s%s%s%s%s",
Contact->GetScreenName(),
Contact->IsAway() ? "(" : "",
Contact->IsAway() ? Contact->GetAwayReason() : "",
Contact->IsAway() ? ")" : "",
ShowIps ? " " : "",
ShowIps ? "(" : "",
ShowIps ? Contact->GetHostName().Get() : "",
ShowIps ? ")" : "");
InsertItem(++Current, buf, Icon);
Contact->ListItem = Current;
}
}
pos = List.GetHeadPosition();
Count = 0;
while (pos)
{
CContact *Contact = List.GetNext(pos);
if (Contact->IsOffline())
Count++;
}
pos = List.GetHeadPosition();
sprintf(buf, "Offline (%d)", Count);
InsertItem(++Current, buf, -1);
OfflineItem = Current;
while (pos)
{
CContact *Contact = List.GetNext(pos);
if (Contact->IsOffline())
{
char buf[512];
int Icon = 1;
if (Contact->IsAway())
Icon = 3;
if (Contact->IsBlocked())
Icon = 2;
sprintf(buf, "%s %s%s%s%s%s%s%s",
Contact->GetScreenName(),
Contact->IsAway() ? "(" : "",
Contact->IsAway() ? Contact->GetAwayReason() : "",
Contact->IsAway() ? ")" : "",
ShowIps ? " " : "",
ShowIps ? "(" : "",
ShowIps ? Contact->GetHostName().Get() : "",
ShowIps ? ")" : "");
InsertItem(++Current, ShowIps ? buf: Contact->GetScreenName(), Icon);
Contact->ListItem = Current;
}
}
}
void CContactView::OnRButtonDown(UINT nFlags, CPoint point)
{
CListCtrl::OnRButtonDown(nFlags, point);
RedrawWindow();
if (GetSelectionMark() < 0 || GetSelectionMark() == 1 || GetSelectionMark() == OfflineItem) return;
RECT rect;
GetItemRect(GetSelectionMark(), &rect, LVIR_BOUNDS);
if (point.x > rect.left && point.x < rect.right && point.y > rect.top && point.y < rect.bottom)
{
CPoint pos;
CMenu &theMenu = GetApp()->MainFrame->RightClickMenu;
CWnd* pTarget = AfxGetMainWnd();
CMenu *subMenu;
CContact *Contact = GetFromListItem(GetSelectionMark());
if (GetSelectionMark() == 0)
{
subMenu = (CMenu *)theMenu.GetSubMenu(1);
}
else
{
subMenu = (CMenu *)theMenu.GetSubMenu(0);
subMenu->SetDefaultItem(0, TRUE);
if (Contact->IsBlocked())
{
subMenu->ModifyMenu(ID_IDRRIGHTCLICK_BLOCK, MF_STRING | MF_BYCOMMAND, ID_IDRRIGHTCLICK_BLOCK, "Unblock");
}
else
{
subMenu->ModifyMenu(ID_IDRRIGHTCLICK_BLOCK, MF_STRING | MF_BYCOMMAND, ID_IDRRIGHTCLICK_BLOCK, "Block");
}
}
GetCursorPos(&pos);
pTarget->SetForegroundWindow();
subMenu->TrackPopupMenu(0, pos.x, pos.y, pTarget, NULL);
pTarget->PostMessage(WM_NULL, 0, 0);
}
}
void CContactView::NotifyOthers()
{
if (Notify) return;
Notify = new CNotifyThread;
Notify->List = &List;
Notify->mainWnd = mainWnd;
Notify->view = this;
Notify->CreateThread();
}
void CContactView::MenuCmd(int item, int cmd)
{
CContact *Contact = GetFromListItem(item);
CNetmsgView *View = (CNetmsgView *)GetParent();
switch (cmd)
{
case MENU_BLOCK:
{
if (!IsContact(Contact))
return;
if (Contact->IsBlocked())
Contact->SetBlocked(false, AfxGetMainWnd()->GetSafeHwnd());
else
Contact->SetBlocked(true, AfxGetMainWnd()->GetSafeHwnd());
break;
}
case MENU_SEND:
{
if (!IsContact(Contact))
return;
NewConversation(Contact, NULL);
break;
}
case MENU_NEWCONTACT:
{
char host[64];
if (CNewContact(mainWnd, host).DoModal() == IDOK)
{
IP Ip(host);
CNetmsgView *View = (CNetmsgView *)GetParent();
if (View->IsMyIp(Ip))
{
MessageBox("The address you entered belongs to an interface on this machine therefore it cannot be added.", "Cannot add contact", MB_OK|MB_ICONSTOP);
return;
}
AddContact(IP(host));
}
break;
}
case MENU_DELETE:
{
DeleteContact(GetFromListItem(item));
break;
}
case MENU_SENDFILE:
{
StartFileTransfer(GetSafeHwnd(), Contact, true);
break;
}
case MENU_AWAY:
{
if (Me.IsOffline()) SetMeOffline(false);
View->PrepareMessage(true, MESSAGE_AWAY);
break;
}
case MENU_APPEAROFFLINE:
{
if (Me.IsAway()) Me.SetAway(false, "");
if (View->HasMessage) View->PrepareMessage(false, NULL);
SetMeOffline(true);
break;
}
case MENU_CHANGENAME:
{
CNetmsgView *View = (CNetmsgView *)GetParent();
View->PrepareMessage(true, MESSAGE_CHANGENAME);
break;
}
case MENU_SETNORMAL:
{
if (View->HasMessage) View->PrepareMessage(false, NULL);
if (Me.IsAway())
{
Me.SetAway(false, "");
}
else if (Me.IsOffline())
{
SetMeOffline(false);
}
break;
}
}
}
void CContactView::SaveContacts()
{
chdir(cwd);
HANDLE hFile;
unsigned long written;
hFile = CreateFile("contacts.dat", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);
if (!hFile) return;
if (hFile == (void *)0xFFFFFFFF) return;
POSITION pos;
pos = List.GetHeadPosition();
char screenname[512];
int sz, total = List.GetCount();
strcpy(screenname, Me.GetScreenName());
sz = strlen(screenname);
WriteFile(hFile, &sz, sizeof(int), &written, NULL);
WriteFile(hFile, screenname, sizeof(char) * strlen(screenname), &written, NULL);
WriteFile(hFile, &total, sizeof(int), &written, NULL);
while (pos)
{
CContact *Contact = List.GetNext(pos);
unsigned char seg1, seg2, seg3, seg4, onblock;
strcpy(screenname, Contact->GetScreenName());
sz = strlen(screenname);
WriteFile(hFile, &sz, sizeof(int), &written, NULL);
WriteFile(hFile, screenname, sizeof(char) * strlen(screenname), &written, NULL);
seg1 = Contact->GetHostName().seg1;
seg2 = Contact->GetHostName().seg2;
seg3 = Contact->GetHostName().seg3;
seg4 = Contact->GetHostName().seg4;
WriteFile(hFile, &seg1, sizeof(unsigned char), &written, NULL);
WriteFile(hFile, &seg2, sizeof(unsigned char), &written, NULL);
WriteFile(hFile, &seg3, sizeof(unsigned char), &written, NULL);
WriteFile(hFile, &seg4, sizeof(unsigned char), &written, NULL);
if (Contact->IsBlocked()) onblock = 1;
else onblock = 0;
WriteFile(hFile, &onblock, sizeof(unsigned char), &written, NULL);
}
CloseHandle(hFile);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -