⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 contactview.cpp

📁 vc++6.0开发网络典型应用实例导航 1. 本光盘提供了本书中所有的实例源程序文件。 2. 附录文件夹下是Winsock 函数参考以及错误码列表
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -