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

📄 myicqdlg.cpp

📁 局域网ICQ的源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   copyright            : (C) 2002 by Zhang Yong                         *
 *   email                : z-yong163@163.com                              *
 ***************************************************************************/

// myicqDlg.cpp : implementation file
//

#include "stdafx.h"
#include "myicq.h"
#include "myicqDlg.h"
#include <mmsystem.h>
#include "serversession.h"
#include "tcpsession.h"
#include "icqwindow.h"
#include "icqdb.h"
#include "icqconfig.h"
#include "icqplugin.h"

#include "GfxPopupMenu.h"
#include "LoginDlg.h"
#include "RegWizard.h"
#include "ViewDetailDlg.h"
#include "SendMsgDlg.h"
#include "SearchWizard.h"
#include "SysMsgDlg.h"
#include "ViewMsgDlg.h"
#include "SysHistoryDlg.h"
#include "DelFriendDlg.h"
#include "ModifyDetailDlg.h"
#include "SysOptionDlg.h"
#include "LoginAgainDlg.h"
#include "NotifyWnd.h"
#include "AboutDlg.h"
#include "MsgMgrWnd.h"
#include "SendRequestDlg.h"
#include "BroadcastDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define ID_GFX_SHOWONLINE		50001
#define ID_GFX_RENAME			50002
#define ID_GFX_REMOVE			50003
#define ID_STATUS_AWAY			40000
#define ID_PLUGIN				60000
#define ID_SKIN_FIRST			70000

#define IDC_OUTBAR				1001
#define ID_HOTKEY				1002
#define ID_TOOLTIP				1003
#define ID_NOTIFYICON			1004

#define IDT_RESEND				1001
#define IDT_KEEPALIVE			1002
#define IDT_STATUS				1003
#define IDT_BLINK				1004
#define IDT_DBLCLK				1005
#define IDT_HOVER				1006
#define IDT_AUTO_SWITCH_STATUS	1007

#define WM_HOSTFOUND			(WM_USER + 101)
#define WM_NOTIFYICON			(WM_USER + 102)

#define HOTKEY_DEFAULT	MAKELONG(0x5a, MOD_CONTROL | MOD_ALT)

enum {
	ALIGN_NONE,
	ALIGN_TOP,
	ALIGN_LEFT,
	ALIGN_RIGHT
};

/////////////////////////////////////////////////////////////////////////////
// CIcqDlg dialog

CIcqDlg::CIcqDlg(CWnd* pParent /*=NULL*/)
: CCaptionBtnDlg(2, CIcqDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CIcqDlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32

	iconBlank = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_BLANK),
		IMAGE_ICON, 0, 0, 0);
	iconSysMsg = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_SYSMSG),
		IMAGE_ICON, 0, 0, 0);

	regMode = -1;
	alignType = ALIGN_NONE;
	isHide = FALSE;
	currentMenu = NULL;
	curContact = NULL;

	outbarCtrl.setListener(this);
	outbarCtrl.setImageList(&getApp()->largeImageList, &getApp()->smallImageList);
}

CIcqDlg::~CIcqDlg()
{
}

void *CIcqDlg::getFaceIcon(int face, int status)
{
	int i = getApp()->getImageIndex(face, status);
	return (void *) getApp()->largeImageList.ExtractIcon(i);
}

void CIcqDlg::popupMsg(void *icon, const char *text, uint32 t)
{
	new CNotifyWnd((HICON) icon, text, t);
}

void CIcqDlg::drawCaptionBtn(CDC *pDC, CRect &rc, int button, BOOL pressed)
{
	ASSERT(button < 2);

	if (!pressed) {
		pDC->Draw3dRect(rc, GetSysColor(COLOR_BTNHILIGHT), GetSysColor(COLOR_3DDKSHADOW));
		rc.InflateRect(-1, -1);
		pDC->Draw3dRect(rc, GetSysColor(COLOR_BTNFACE), GetSysColor(COLOR_3DSHADOW));
	} else {
		pDC->Draw3dRect(rc, GetSysColor(COLOR_3DDKSHADOW), GetSysColor(COLOR_BTNHILIGHT));
		rc.InflateRect(-1, -1);
		pDC->Draw3dRect(rc, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_BTNFACE));
	}

	rc.InflateRect(-1, -1);
	pDC->FillSolidRect(rc, GetSysColor(COLOR_BTNFACE));

	CPen pen(PS_SOLID, 1, GetSysColor(COLOR_BTNTEXT));
	CPen *penOld = pDC->SelectObject(&pen);
	int x, y;

	x = rc.left;
	y = (rc.top + rc.bottom) / 2;
	if (pressed) {
		x++;
		y++;
	}
	pDC->MoveTo(x, y);
	pDC->LineTo(x + rc.Width() - 2, y);

	if (button == 1) {
		x = (rc.left + rc.right) / 2 - 1;
		y = rc.top + 1;
		if (pressed) {
			x++;
			y++;
		}
		pDC->MoveTo(x, y);
		pDC->LineTo(x, y + rc.Height() - 2);
	}

	pDC->SelectObject(penOld);
}

void CIcqDlg::onCaptionBtnClicked(int button)
{
	ASSERT(button < 2);

	if (button == 0) {
		ShowWindow(SW_MINIMIZE);
		ShowWindow(SW_HIDE);
	} else if (button == 1) {
		CGfxPopupMenu menu;
		menu.CreatePopupMenu();

		int id = 1000;
		menu.appendMenu(id, options.skin.empty() ? IDB_CHECK : IDB_FOLDER, IDS_SKIN_RESTORE);

		CFileFind finder;
		BOOL cont = finder.FindFile(getApp()->rootDir + "skins\\*");
		while (cont) {
			cont = finder.FindNextFile();
			if (!finder.IsDots() && finder.IsDirectory()) {
				int bmpID = (finder.GetFileTitle() == options.skin.c_str() ? IDB_CHECK : IDB_FOLDER);
				menu.appendMenu(++id, bmpID, finder.GetFileTitle());
			}
		}

		CPoint pt;
		GetCursorPos(&pt);
		id = menu.TrackPopupMenu(TPM_RETURNCMD, pt.x, pt.y, this);
		if (id == 0)
			return;

		ShowWindow(SW_MINIMIZE);

		if (id == 1000) {
			outbarCtrl.setSkin(NULL);
			options.skin = "";
		} else {
			CString str;
			menu.GetMenuString(id, str, 0);
			if (skin.load(getApp()->rootDir + "skins\\" + str))
				outbarCtrl.setSkin(&skin);

			options.skin = str;
		}

		IcqDB::saveOptions(options);
		ShowWindow(SW_NORMAL);
	}
}

void CIcqDlg::onSendError(uint32 seq)
{
	if (!seq) {
		// Destination port is unreachable.
		IcqWindow *win = findWindow(WIN_REG_WIZARD);
		if (win) {
			((CRegWizard *) win)->onSendError(seq);
			return;
		}
	} else if (lastSeq != seq) {
		IcqLink::onSendError(seq);
		return;
	}

	lastSeq = 0;
	onError();
}

void CIcqDlg::onConnect(bool success)
{
	IcqWindow *win = findWindow(WIN_REG_WIZARD);
	if (win) {
		((CRegWizard *) win)->onConnect(success);
		return;
	}

	if (success)
		lastSeq = serverSession()->login(myInfo.passwd.c_str(), pendingStatus);
	else {
		myInfo.status = STATUS_OFFLINE;
		updateStatusIcon();
		logout();
	}
}

IcqContact *CIcqDlg::addContact(uint32 uin, int folder)
{
	outbarCtrl.removeContact(uin);
	
	IcqContact *c = findContact(uin);
	if (!c) {
		c = new IcqContact;
		c->uin = uin;
		CString nick;
		nick.Format("%lu", uin);
		c->nick = nick;
		contactList.push_back(c);
	}
	
	int n = outbarCtrl.getFolderCount();
	if (folder == n - 1)
		c->type = CONTACT_IGNORE;
	else if (folder == n - 2)
		c->type = CONTACT_STRANGER;
	else
		c->type = CONTACT_FRIEND;
	
	outbarCtrl.addContact(folder, c);
	outbarCtrl.repaintInsideRect();
	saveGroupInfo();
	return c;
}

void CIcqDlg::login(uint32 status)
{
	pendingStatus = status;
	
	SetTimer(IDT_STATUS, 250, NULL);
	m_btnStatus.setText(IDS_STATUS_LOGGING_IN);

	resolveHost();
}

void CIcqDlg::logout()
{
	IcqLink::logout();

	KillTimer(IDT_RESEND);
	KillTimer(IDT_KEEPALIVE);
	KillTimer(IDT_AUTO_SWITCH_STATUS);

	PtrList::iterator it;
	for (it = contactList.begin(); it != contactList.end(); ++it) {
		IcqContact *c = (IcqContact *) *it;
		outbarCtrl.update(c->uin, TRUE);
	}
}

void CIcqDlg::addFriend(IcqContact *c, int folder)
{
	if (folder < 0)
		folder = outbarCtrl.getSelFolder();
	c->type = CONTACT_FRIEND;

	CSysMsgDlg *win = new CSysMsgDlg(c->uin);
	win->Create(IDD_SYS_MESSAGE);
}

BOOL CIcqDlg::delFriend(IcqContact *c, int folder)
{
	CString str;
	str.Format(IDS_PROMPT_DEL_FRIEND, c->uin);
	if (AfxMessageBox(str, MB_YESNO) != IDYES)
		return FALSE;

	{
		CDelFriendDlg dlg(c->uin);
		if (dlg.DoModal() != IDOK)
			return FALSE;
	}
		
	int n = outbarCtrl.getFolderCount();
	if (folder == n - 1 || folder < 0)
		destroyContact(c->uin);
	
	if (folder == n - 2 || folder < 0)
		IcqDB::delContact(c->uin);
	outbarCtrl.removeContact(c->uin);
	if (folder >= 0) {
		outbarCtrl.addContact(folder, c);
		saveGroupInfo();
		c->type = (folder == n - 1 ? CONTACT_IGNORE : CONTACT_STRANGER);
	} else {
		contactList.remove(c);
		delete c;
	}
	return TRUE;
}

void CIcqDlg::onHostFound(in_addr &addr)
{
	if (addr.s_addr != INADDR_NONE)
		serverSession()->connect(inet_ntoa(addr), options.port);
	else
		onError();
}

void CIcqDlg::onlineNotify(IcqContact *c)
{
	if (options.flags.test(UF_ONLINE_NOTIFY)) {
		options.playSound(SOUND_ONLINE, c);
		outbarCtrl.blinkText(c->uin);

		if (c->flags.test(CF_OPTION_POPUP_ONLINE)) {
			CString str;
			str.Format(IDS_NOTIFY_ONLINE, c->nick.c_str(), c->uin);
			new CNotifyWnd(getApp()->largeImageList.ExtractIcon(c->face), str);
		}
	}
}

void CIcqDlg::addNotifyIcon()
{
	NOTIFYICONDATA tnid;

	tnid.cbSize = sizeof(NOTIFYICONDATA);
	tnid.hWnd = m_hWnd;
	tnid.uID = ID_NOTIFYICON;
	tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
	tnid.uCallbackMessage = WM_NOTIFYICON;
	tnid.hIcon = getApp()->m_hIcon;
	lstrcpy(tnid.szTip, AfxGetAppName());

	Shell_NotifyIcon(NIM_ADD, &tnid);
}

void CIcqDlg::removeNotifyIcon()
{
	NOTIFYICONDATA tnid;

	tnid.cbSize = sizeof(NOTIFYICONDATA);
	tnid.hWnd = m_hWnd;
	tnid.uID = ID_NOTIFYICON;

	Shell_NotifyIcon(NIM_DELETE, &tnid);
}

void CIcqDlg::modifyNotifyIcon(HICON hIcon)
{
	NOTIFYICONDATA tnid;

	tnid.cbSize = sizeof(NOTIFYICONDATA);
	tnid.hWnd = m_hWnd;
	tnid.uID = ID_NOTIFYICON;
	tnid.uFlags = NIF_ICON;
	tnid.hIcon = hIcon;

	Shell_NotifyIcon(NIM_MODIFY, &tnid);
}

void CIcqDlg::popupMainMenu(UINT nFlags, CPoint &pt)
{
	CGfxPopupMenu menu;
	CMenu tmp;
	tmp.LoadMenu(IDR_MAIN);
	menu.Attach(*tmp.GetSubMenu(0));
	CGfxPopupMenu fileMenu;
	fileMenu.Attach(*menu.GetSubMenu(0));

	fileMenu.modifyMenu(ID_MESSAGE_MGR, IDB_MSG_HISTORY);
	fileMenu.modifyMenu(ID_CONTACT_MGR, IDB_CONTACT_MGR);

	menu.modifyMenu(0, IDB_FILEMGR, FALSE);
	menu.modifyMenu(ID_CHANGE_USER, IDB_CHANGE_USER);
	menu.modifyMenu(ID_REG_WIZARD, IDB_REG_WIZARD);
	menu.modifyMenu(ID_MODIFY_INFO, IDB_VIEW_DETAIL);
	menu.modifyMenu(ID_SYS_OPTION, IDB_SYS_OPTION);
	menu.modifyMenu(ID_HELP, IDB_HELP);
	menu.modifyMenu(ID_APP_EXIT, IDB_EXIT);
	if (myInfo.uin >= 1000)
		menu.DeleteMenu(ID_BROADCAST_MSG, 0);
	else
		menu.modifyMenu(ID_BROADCAST_MSG, iconSysMsg);

	menu.setVertBitmap(IDB_VERT);

	currentMenu = &menu;
	menu.TrackPopupMenu(nFlags, pt.x, pt.y, this);
	currentMenu = NULL;
}

void CIcqDlg::popupStatusMenu(UINT nFlags, CPoint &pt)
{
	CMenu tmp;
	tmp.LoadMenu(IDR_STATUS);
	CGfxPopupMenu statusMenu;
	statusMenu.Attach(*tmp.GetSubMenu(0));
	CGfxPopupMenu awayMenu;
	awayMenu.Attach(*statusMenu.GetSubMenu(2));

	statusMenu.modifyMenu(ID_STATUS_ONLINE, IDB_STATUS_ONLINE);
	statusMenu.modifyMenu(2, IDB_STATUS_AWAY, FALSE);
	statusMenu.modifyMenu(ID_STATUS_INVIS, IDB_STATUS_INVIS);
	statusMenu.modifyMenu(ID_STATUS_OFFLINE, IDB_STATUS_OFFLINE);

	bool autoReply = options.flags.test(UF_AUTO_REPLY);
	UINT bitmap;

	StrList l;
	IcqDB::loadAutoReply(l);
	int pos = 0;
	UINT id = ID_STATUS_AWAY;
	StrList::iterator it;
	for (it = l.begin(); it != l.end(); ++it) {
		bitmap = (autoReply && *it == options.autoReplyText) ?
			IDB_STATUS_AWAY : IDB_STATUS_OFFLINE;
		CString str = (*it).c_str();
		if (str.GetLength() > 20)
			str = str.Left(20) + "...";
		awayMenu.InsertMenu(pos, MF_BYPOSITION, id++, str);
		awayMenu.modifyMenu(pos++, bitmap, FALSE);
		awayMenu.InsertMenu(pos++, MF_SEPARATOR | MF_BYPOSITION);
	}

	bitmap = autoReply ? IDB_STATUS_OFFLINE : IDB_STATUS_AWAY;
	awayMenu.modifyMenu(ID_STATUS_AWAY_NOREPLY, bitmap);
	awayMenu.modifyMenu(ID_STATUS_AWAY_CUSTOM, IDB_SYS_OPTION);

	currentMenu = &statusMenu;
	statusMenu.TrackPopupMenu(nFlags, pt.x, pt.y, this);
	currentMenu = NULL;
}

void CIcqDlg::updateStatusIcon()
{
	KillTimer(IDT_STATUS);

	switch (myInfo.status) {
	case STATUS_ONLINE:
		m_btnStatus.setText(IDS_STATUS_ONLINE);
		break;
	case STATUS_OFFLINE:
		m_btnStatus.setText(IDS_STATUS_OFFLINE);
		break;
	case STATUS_AWAY:
		m_btnStatus.setText(IDS_STATUS_AWAY);
		break;
	case STATUS_INVIS:
		m_btnStatus.setText(IDS_STATUS_INVIS);
		break;
	}

	HICON hIcon = statusImgList.ExtractIcon(myInfo.status);
	m_btnStatus.SetIcon(hIcon);
	modifyNotifyIcon(hIcon);
}

void CIcqDlg::animateStatus()
{
	SetTimer(IDT_STATUS, 250, NULL);
	OnTimer(IDT_STATUS);
}

void CIcqDlg::hideWindow(BOOL hide)
{
	CRect rc;
	GetWindowRect(rc);
	int moves = 20;
	int xStep, yStep;
	int xEnd, yEnd;
	int cxScreen;

	switch (alignType) {
	case ALIGN_TOP:
		xStep = 0;
		xEnd = rc.left;
		if (hide) {
			yStep = -rc.bottom / moves;
			yEnd = -rc.Height() + 2;
		} else {
			yStep = -rc.top / moves;
			yEnd = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -