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

📄 myicqctrl.cpp

📁 局域网ICQ的源代码
💻 CPP
字号:
/***************************************************************************
 *                                                                         *
 *   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                              *
 ***************************************************************************/

// MyICQCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "myicq.h"
#include "MyICQCtrl.h"
#include "icqlink.h"
#include "icqclient.h"
#include "icqskin.h"

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

class ContactItem : public OutBarItem {
public:
	ContactItem(IcqContact *c)
		:OutBarItem(c->nick.c_str(), getApp()->getImageIndex(c->face, c->status)),
		contact(c) {}
	int compare(ContactItem *item);
	
	IcqContact *contact;
};

int ContactItem::compare(ContactItem *item)
{
	BOOL b1 = (contact->status != STATUS_OFFLINE);
	BOOL b2 = (item->contact->status != STATUS_OFFLINE);
	if (b1 != b2)
		return (b1 ? -1 : 1);

	int ret = text.Compare(item->text);
	if (ret != 0)
		return ret;

	return (contact->uin > item->contact->uin ? 1 : -1);
}


static COLORREF blinkColors[] = {
	RGB(255, 0, 0),
	RGB(255, 255, 0),
	RGB(0, 255, 255),
	RGB(0, 255, 0),
	RGB(0, 0, 255),
};
#define NR_BLINK_COLORS	(sizeof(blinkColors) / sizeof(*blinkColors))

#define BLINK_OFFSET	3
static CPoint blinkOffsets[] = {
	CPoint(0, 0),
	CPoint(BLINK_OFFSET, BLINK_OFFSET),
	CPoint(0, 0),
	CPoint(-BLINK_OFFSET, BLINK_OFFSET),
};
#define NR_BLINK_OFFSETS	(sizeof(blinkOffsets) / sizeof(*blinkOffsets))

#define IDT_BLINK_TEXT		2001
#define IDT_BLINK_IMAGE		2002

/////////////////////////////////////////////////////////////////////////////
// MyICQCtrl

MyICQCtrl::MyICQCtrl()
{
	onlineOnly = FALSE;
	skin = NULL;
}

MyICQCtrl::~MyICQCtrl()
{
}

IcqContact *MyICQCtrl::contact(int folder, int item)
{
	return ((ContactItem *) folders[folder]->items[item])->contact;
}

void MyICQCtrl::update(uint32 uin, BOOL move)
{
	int folder, item;
	if (findItem(uin, folder, item)) {
		vector<OutBarItem *> &items = folders[folder]->items;
		ContactItem *p = (ContactItem *) items[item];
		IcqContact *c = p->contact;
		
		if (move) {
			items.erase(items.begin() + item);
			addContact(folder, c);
			delete p;
		} else {
			p->image = getApp()->getImageIndex(c->face, c->status);
			p->text = c->nick.c_str();
		}
		
		if (folder == selFolder)
			repaintInsideRect();
	}
}

void MyICQCtrl::addContact(int folder, IcqContact *c)
{
	if (folder < 0 || folder >= getFolderCount())
		return;
		
	ContactItem *p = new ContactItem(c);
	vector<OutBarItem *> &items = folders[folder]->items;
	int low = 0, high = items.size() - 1;
	while (low <= high) {
		int mid = (low + high) / 2;
		if (p->compare((ContactItem *) items[mid]) > 0)
			low = mid + 1;
		else
			high = mid - 1;
	}
	insertItem(folder, low, p);
}

void MyICQCtrl::removeContact(uint32 uin)
{
	int folder, item;
	if (findItem(uin, folder, item)) {
		vector<OutBarItem *> &items = folders[folder]->items;
		items.erase(items.begin() + item);
		if (selFolder == folder)
			repaintInsideRect();
	}
}

BOOL MyICQCtrl::findItem(uint32 uin, int &folder, int &item)
{
	for (int i = 0; i < (int) folders.size(); i++) {
		vector<OutBarItem *> &items = folders[i]->items;
		for (int j = 0; j < (int) items.size(); j++) {
			if (((ContactItem *)items[j])->contact->uin == uin) {
				folder = i;
				item = j;
				return TRUE;
			}
		}
	}
	return FALSE;
}

void MyICQCtrl::doBlinkText()
{
	CClientDC dc(this);
	CRect rc;
	getInsideRect(rc);
	CRgn rgn;
	rgn.CreateRectRgnIndirect(rc);
	dc.SelectClipRgn(&rgn);
	
	BlinkList::iterator it, next;
	for (it = blinkTextList.begin(); it != blinkTextList.end(); it = next) {
		next = it;
		++next;

		BlinkInfo *p = &(*it);
		int folder, item;
		if (findItem(p->uin, folder, item)) {
			p->frame--;
			if (folder != selFolder || item > getMaxVisibleItem())
				continue;
			if (p->frame >= 0) {
				drawItemText(&dc, item, blinkColors[p->frame % NR_BLINK_COLORS]);
				continue;
			}
			drawItemText(&dc, item, fontColor);
		}
		blinkTextList.erase(it);
	}
	if (blinkTextList.empty())
		KillTimer(IDT_BLINK_TEXT);
}

void MyICQCtrl::doBlinkImage()
{
	if (blinkImageList.empty()) {
		KillTimer(IDT_BLINK_IMAGE);
		return;
	}
	BlinkInfo *p = &blinkImageList.back();
	int folder, item;
	if (!findItem(p->uin, folder, item)) {
		blinkImageList.pop_back();
		return;
	}
	int img = folders[folder]->items[item]->image;
	
	CClientDC dc(this);
	CRect rc;
	getFolderRect(rc, folder);
	rc.left += 2;
	rc.right = rc.left + SMALL_ICON_W;
	rc.top += (FOLDER_HEIGHT - SMALL_ICON_H) / 2;
	rc.bottom = rc.top + SMALL_ICON_H;
	if (p->frame & 1)
		drawFolder(&dc, folder, FALSE, FALSE);
	else
		smallIcons->Draw(&dc, img, rc.TopLeft(), ILD_TRANSPARENT);
	
	getInsideRect(rc);
	CRgn rgn;
	rgn.CreateRectRgnIndirect(rc);
	dc.SelectClipRgn(&rgn);

	BlinkList::iterator it;
	for (it = blinkImageList.begin(); it != blinkImageList.end(); ++it) {
		p = &(*it);
		if (!findItem(p->uin, folder, item))
			continue;

		p->frame++;
		if (p->frame >= (int) NR_BLINK_OFFSETS)
			p->frame = 0;
		if (folder != selFolder || item > getMaxVisibleItem())
			continue;

		CRect rcIcon;
		getIconRect(rc, item);
		rcIcon = rc;
		rcIcon.InflateRect(BLINK_OFFSET, BLINK_OFFSET);
		drawBackground(&dc, rcIcon);
		CPoint &pt = blinkOffsets[p->frame];
		rc.OffsetRect(pt.x, pt.y);
		drawItemImage(&dc, item, rc);
	}
}

void MyICQCtrl::blinkText(uint32 uin)
{
	int folder, item;
	if (!findItem(uin, folder, item))
		return;
		
	SetTimer(IDT_BLINK_TEXT, 300, NULL);
	blinkTextList.push_back(BlinkInfo(uin, 5 * NR_BLINK_COLORS));
}

void MyICQCtrl::blinkImage(uint32 uin, BOOL blink)
{
	if (blink) {
		int folder, item;
		if (!findItem(uin, folder, item))
			return;
		
		SetTimer(IDT_BLINK_IMAGE, 400, NULL);
		blinkImageList.push_back(BlinkInfo(uin, 0));
	} else {
		BlinkList::iterator it = blinkImageList.begin();
		while (it != blinkImageList.end()) {
			if ((*it).uin == uin)
				it = blinkImageList.erase(it);
			else
				++it;
		}
		if (blinkImageList.empty())
			KillTimer(IDT_BLINK_IMAGE);
		Invalidate();
	}
}

void MyICQCtrl::save(DBOutStream &out)
{
	out << bgColor << fontColor;
	out << (uint8) largeIconView;
	
	uint16 nrFolders = folders.size();
	out << nrFolders;
	for (int i = 0; i < nrFolders; i++) {
		OutBarFolder *f = folders[i];
		out << f->text;
		
		uint16 nrItems = f->items.size();
		out << nrItems;
		for (int j = 0; j < nrItems; j++)
			out << ((ContactItem *) f->items[j])->contact->uin;
	}
}

void MyICQCtrl::load(DBInStream &in)
{
	int i;
	for (i = folders.size() - 1; i >= 0; i--)
		delete folders[i];
	folders.clear();

	in >> bgColor >> fontColor;
	uint8 b;
	in >> b;
	largeIconView = b;

	uint16 nrFolders;
	in >> nrFolders;
	for (i = 0; i < nrFolders; i++) {
		string name;
		in >> name;
		addFolder(name.c_str());
		
		uint16 nrItems;
		in >> nrItems;
		for (int j = 0; j < nrItems; j++) {
			uint32 uin;
			in >> uin;
			IcqContact *c = icqLink->findContact(uin);
			if (c) {
				c->type = (i < nrFolders - 1 ? CONTACT_FRIEND : CONTACT_IGNORE);
				addContact(i, c);
			}
		}
	}
}

int MyICQCtrl::getMaxVisibleItem()
{
	int max = OutBarCtrl::getMaxVisibleItem();
	if (onlineOnly) {
		for (; max >= 0; --max) {
			if (contact(max)->status != STATUS_OFFLINE)
				break;
		}
	}
	return max;
}

void MyICQCtrl::drawBackground(CDC *pDC, CRect &rc)
{
	if (!skin) {
		OutBarCtrl::drawBackground(pDC, rc);
		return;
	}

	CBitmap &back = skin->bitmaps[SKIN_BACK];
	BITMAP bm;
	back.GetBitmap(&bm);
	CDC memDC;
	memDC.CreateCompatibleDC(pDC);
	CBitmap *oldBitmap = memDC.SelectObject(&back);

	for (int y = rc.top; y < rc.bottom; y += bm.bmHeight) {
		int h = bm.bmHeight;
		if (h > rc.bottom - y)
			h = rc.bottom - y;
		for (int x = rc.left; x < rc.right; x += bm.bmWidth) {
			int w = bm.bmWidth;
			if (w > rc.right - x)
				w = rc.right - x;
			pDC->BitBlt(x, y, w, h, &memDC, 0, 0, SRCCOPY);
		}
	}

	memDC.SelectObject(oldBitmap);
}

void MyICQCtrl::drawItemText(CDC *pDC, int i, COLORREF color)
{
	OutBarCtrl::drawItemText(pDC, i,
		contact(i)->status == STATUS_AWAY ? RGB(0, 0, 255) : color);
}

void MyICQCtrl::drawFolder(CDC *pDC, int i, BOOL pressed, BOOL hilight)
{
	if (!skin) {
		OutBarCtrl::drawFolder(pDC, i, pressed, hilight);
		return;
	}
	
	if (pressed)
		hilight = FALSE;
	CBitmap *bm = &skin->bitmaps[hilight ? SKIN_FOLDER_LIGHT : SKIN_FOLDER];

	CRect rc;
	getFolderRect(rc, i);
	int l = rc.left;
	int r = rc.right;
	CDC memDC;
	memDC.CreateCompatibleDC(pDC);
	CBitmap *oldBitmap = memDC.SelectObject(bm);
	BITMAP info;
	bm->GetBitmap(&info);

	pDC->BitBlt(l, rc.top, 40, info.bmHeight, &memDC, 0, 0, SRCCOPY);
	l += 40;
	r -= 40;
	pDC->BitBlt(r, rc.top, 40, info.bmHeight, &memDC, info.bmWidth - 40, 0, SRCCOPY);

	info.bmWidth -= 40 * 2;
	while (l < r) {
		int w = info.bmWidth;
		if (w > r - l)
			w = r - l;
		pDC->BitBlt(l, rc.top, w, info.bmHeight, &memDC, 40, 0, SRCCOPY);
		l += info.bmWidth;
	}

	memDC.SelectObject(oldBitmap);

	drawFolderText(pDC, i, rc);
}

void MyICQCtrl::drawScroll(CDC *pDC, int i, BOOL pressed)
{
	if (!skin) {
		OutBarCtrl::drawScroll(pDC, i, pressed);
		return;
	}

	CBitmap *scroll;
	if (i == SCROLL_DIR_UP)
		scroll = &skin->bitmaps[pressed ? SKIN_SCROLLUP_PRESSED : SKIN_SCROLLUP];
	else
		scroll = &skin->bitmaps[pressed ? SKIN_SCROLLDOWN_PRESSED : SKIN_SCROLLDOWN];

	CDC memDC;
	memDC.CreateCompatibleDC(pDC);
	CBitmap *oldBitmap = memDC.SelectObject(scroll);
	CRect rc;
	getScrollRect(rc, i);

	BITMAP bm;
	scroll->GetBitmap(&bm);
	pDC->BitBlt(rc.left, rc.top, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);

	memDC.SelectObject(oldBitmap);
}

BEGIN_MESSAGE_MAP(MyICQCtrl, OutBarCtrl)
	//{{AFX_MSG_MAP(MyICQCtrl)
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// MyICQCtrl message handlers

void MyICQCtrl::OnTimer(UINT nIDEvent) 
{
	if (nIDEvent == IDT_BLINK_TEXT)
		doBlinkText();
	else if (nIDEvent == IDT_BLINK_IMAGE)
		doBlinkImage();
	else
		OutBarCtrl::OnTimer(nIDEvent);
}

⌨️ 快捷键说明

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