MyICQCtrl.cpp
上传用户:zslianheng
上传日期:2013-04-03
资源大小:946k
文件大小:11k
源码类别:

Linux/Unix编程

开发平台:

Visual C++

  1. /***************************************************************************
  2.  *                                                                         *
  3.  *   This program is free software; you can redistribute it and/or modify  *
  4.  *   it under the terms of the GNU General Public License as published by  *
  5.  *   the Free Software Foundation; either version 2 of the License, or     *
  6.  *   (at your option) any later version.                                   *
  7.  *                                                                         *
  8.  *   copyright            : (C) 2002 by Zhang Yong                         *
  9.  *   email                : z-yong163@163.com                              *
  10.  ***************************************************************************/
  11. // MyICQCtrl.cpp : implementation file
  12. //
  13. #include "stdafx.h"
  14. #include "myicq.h"
  15. #include "MyICQCtrl.h"
  16. #include "icqlink.h"
  17. #include "icqclient.h"
  18. #include "icqskin.h"
  19. #ifdef _DEBUG
  20. #define new DEBUG_NEW
  21. #undef THIS_FILE
  22. static char THIS_FILE[] = __FILE__;
  23. #endif
  24. class ContactItem : public OutBarItem {
  25. public:
  26. ContactItem(IcqContact *c)
  27. :OutBarItem(c->nick.c_str(), getApp()->getImageIndex(c->face, c->status)),
  28. contact(c) {}
  29. int compare(ContactItem *item);
  30. IcqContact *contact;
  31. };
  32. int ContactItem::compare(ContactItem *item)
  33. {
  34. BOOL b1 = (contact->status != STATUS_OFFLINE);
  35. BOOL b2 = (item->contact->status != STATUS_OFFLINE);
  36. if (b1 != b2)
  37. return (b1 ? -1 : 1);
  38. int ret = text.Compare(item->text);
  39. if (ret != 0)
  40. return ret;
  41. return (contact->uin > item->contact->uin ? 1 : -1);
  42. }
  43. static COLORREF blinkColors[] = {
  44. RGB(255, 0, 0),
  45. RGB(255, 255, 0),
  46. RGB(0, 255, 255),
  47. RGB(0, 255, 0),
  48. RGB(0, 0, 255),
  49. };
  50. #define NR_BLINK_COLORS (sizeof(blinkColors) / sizeof(*blinkColors))
  51. #define BLINK_OFFSET 3
  52. static CPoint blinkOffsets[] = {
  53. CPoint(0, 0),
  54. CPoint(BLINK_OFFSET, BLINK_OFFSET),
  55. CPoint(0, 0),
  56. CPoint(-BLINK_OFFSET, BLINK_OFFSET),
  57. };
  58. #define NR_BLINK_OFFSETS (sizeof(blinkOffsets) / sizeof(*blinkOffsets))
  59. #define IDT_BLINK_TEXT 2001
  60. #define IDT_BLINK_IMAGE 2002
  61. /////////////////////////////////////////////////////////////////////////////
  62. // MyICQCtrl
  63. MyICQCtrl::MyICQCtrl()
  64. {
  65. onlineOnly = FALSE;
  66. skin = NULL;
  67. }
  68. MyICQCtrl::~MyICQCtrl()
  69. {
  70. }
  71. IcqContact *MyICQCtrl::contact(int folder, int item)
  72. {
  73. return ((ContactItem *) folders[folder]->items[item])->contact;
  74. }
  75. void MyICQCtrl::update(uint32 uin, BOOL move)
  76. {
  77. int folder, item;
  78. if (findItem(uin, folder, item)) {
  79. vector<OutBarItem *> &items = folders[folder]->items;
  80. ContactItem *p = (ContactItem *) items[item];
  81. IcqContact *c = p->contact;
  82. if (move) {
  83. items.erase(items.begin() + item);
  84. addContact(folder, c);
  85. delete p;
  86. } else {
  87. p->image = getApp()->getImageIndex(c->face, c->status);
  88. p->text = c->nick.c_str();
  89. }
  90. if (folder == selFolder)
  91. repaintInsideRect();
  92. }
  93. }
  94. void MyICQCtrl::addContact(int folder, IcqContact *c)
  95. {
  96. if (folder < 0 || folder >= getFolderCount())
  97. return;
  98. ContactItem *p = new ContactItem(c);
  99. vector<OutBarItem *> &items = folders[folder]->items;
  100. int low = 0, high = items.size() - 1;
  101. while (low <= high) {
  102. int mid = (low + high) / 2;
  103. if (p->compare((ContactItem *) items[mid]) > 0)
  104. low = mid + 1;
  105. else
  106. high = mid - 1;
  107. }
  108. insertItem(folder, low, p);
  109. }
  110. void MyICQCtrl::removeContact(uint32 uin)
  111. {
  112. int folder, item;
  113. if (findItem(uin, folder, item)) {
  114. vector<OutBarItem *> &items = folders[folder]->items;
  115. items.erase(items.begin() + item);
  116. if (selFolder == folder)
  117. repaintInsideRect();
  118. }
  119. }
  120. BOOL MyICQCtrl::findItem(uint32 uin, int &folder, int &item)
  121. {
  122. for (int i = 0; i < (int) folders.size(); i++) {
  123. vector<OutBarItem *> &items = folders[i]->items;
  124. for (int j = 0; j < (int) items.size(); j++) {
  125. if (((ContactItem *)items[j])->contact->uin == uin) {
  126. folder = i;
  127. item = j;
  128. return TRUE;
  129. }
  130. }
  131. }
  132. return FALSE;
  133. }
  134. void MyICQCtrl::doBlinkText()
  135. {
  136. CClientDC dc(this);
  137. CRect rc;
  138. getInsideRect(rc);
  139. CRgn rgn;
  140. rgn.CreateRectRgnIndirect(rc);
  141. dc.SelectClipRgn(&rgn);
  142. BlinkList::iterator it, next;
  143. for (it = blinkTextList.begin(); it != blinkTextList.end(); it = next) {
  144. next = it;
  145. ++next;
  146. BlinkInfo *p = &(*it);
  147. int folder, item;
  148. if (findItem(p->uin, folder, item)) {
  149. p->frame--;
  150. if (folder != selFolder || item > getMaxVisibleItem())
  151. continue;
  152. if (p->frame >= 0) {
  153. drawItemText(&dc, item, blinkColors[p->frame % NR_BLINK_COLORS]);
  154. continue;
  155. }
  156. drawItemText(&dc, item, fontColor);
  157. }
  158. blinkTextList.erase(it);
  159. }
  160. if (blinkTextList.empty())
  161. KillTimer(IDT_BLINK_TEXT);
  162. }
  163. void MyICQCtrl::doBlinkImage()
  164. {
  165. if (blinkImageList.empty()) {
  166. KillTimer(IDT_BLINK_IMAGE);
  167. return;
  168. }
  169. BlinkInfo *p = &blinkImageList.back();
  170. int folder, item;
  171. if (!findItem(p->uin, folder, item)) {
  172. blinkImageList.pop_back();
  173. return;
  174. }
  175. int img = folders[folder]->items[item]->image;
  176. CClientDC dc(this);
  177. CRect rc;
  178. getFolderRect(rc, folder);
  179. rc.left += 2;
  180. rc.right = rc.left + SMALL_ICON_W;
  181. rc.top += (FOLDER_HEIGHT - SMALL_ICON_H) / 2;
  182. rc.bottom = rc.top + SMALL_ICON_H;
  183. if (p->frame & 1)
  184. drawFolder(&dc, folder, FALSE, FALSE);
  185. else
  186. smallIcons->Draw(&dc, img, rc.TopLeft(), ILD_TRANSPARENT);
  187. getInsideRect(rc);
  188. CRgn rgn;
  189. rgn.CreateRectRgnIndirect(rc);
  190. dc.SelectClipRgn(&rgn);
  191. BlinkList::iterator it;
  192. for (it = blinkImageList.begin(); it != blinkImageList.end(); ++it) {
  193. p = &(*it);
  194. if (!findItem(p->uin, folder, item))
  195. continue;
  196. p->frame++;
  197. if (p->frame >= (int) NR_BLINK_OFFSETS)
  198. p->frame = 0;
  199. if (folder != selFolder || item > getMaxVisibleItem())
  200. continue;
  201. CRect rcIcon;
  202. getIconRect(rc, item);
  203. rcIcon = rc;
  204. rcIcon.InflateRect(BLINK_OFFSET, BLINK_OFFSET);
  205. drawBackground(&dc, rcIcon);
  206. CPoint &pt = blinkOffsets[p->frame];
  207. rc.OffsetRect(pt.x, pt.y);
  208. drawItemImage(&dc, item, rc);
  209. }
  210. }
  211. void MyICQCtrl::blinkText(uint32 uin)
  212. {
  213. int folder, item;
  214. if (!findItem(uin, folder, item))
  215. return;
  216. SetTimer(IDT_BLINK_TEXT, 300, NULL);
  217. blinkTextList.push_back(BlinkInfo(uin, 5 * NR_BLINK_COLORS));
  218. }
  219. void MyICQCtrl::blinkImage(uint32 uin, BOOL blink)
  220. {
  221. if (blink) {
  222. int folder, item;
  223. if (!findItem(uin, folder, item))
  224. return;
  225. SetTimer(IDT_BLINK_IMAGE, 400, NULL);
  226. blinkImageList.push_back(BlinkInfo(uin, 0));
  227. } else {
  228. BlinkList::iterator it = blinkImageList.begin();
  229. while (it != blinkImageList.end()) {
  230. if ((*it).uin == uin)
  231. it = blinkImageList.erase(it);
  232. else
  233. ++it;
  234. }
  235. if (blinkImageList.empty())
  236. KillTimer(IDT_BLINK_IMAGE);
  237. Invalidate();
  238. }
  239. }
  240. void MyICQCtrl::save(DBOutStream &out)
  241. {
  242. out << bgColor << fontColor;
  243. out << (uint8) largeIconView;
  244. uint16 nrFolders = folders.size();
  245. out << nrFolders;
  246. for (int i = 0; i < nrFolders; i++) {
  247. OutBarFolder *f = folders[i];
  248. out << f->text;
  249. uint16 nrItems = f->items.size();
  250. out << nrItems;
  251. for (int j = 0; j < nrItems; j++)
  252. out << ((ContactItem *) f->items[j])->contact->uin;
  253. }
  254. }
  255. void MyICQCtrl::load(DBInStream &in)
  256. {
  257. int i;
  258. for (i = folders.size() - 1; i >= 0; i--)
  259. delete folders[i];
  260. folders.clear();
  261. in >> bgColor >> fontColor;
  262. uint8 b;
  263. in >> b;
  264. largeIconView = b;
  265. uint16 nrFolders;
  266. in >> nrFolders;
  267. for (i = 0; i < nrFolders; i++) {
  268. string name;
  269. in >> name;
  270. addFolder(name.c_str());
  271. uint16 nrItems;
  272. in >> nrItems;
  273. for (int j = 0; j < nrItems; j++) {
  274. uint32 uin;
  275. in >> uin;
  276. IcqContact *c = icqLink->findContact(uin);
  277. if (c) {
  278. c->type = (i < nrFolders - 1 ? CONTACT_FRIEND : CONTACT_IGNORE);
  279. addContact(i, c);
  280. }
  281. }
  282. }
  283. }
  284. int MyICQCtrl::getMaxVisibleItem()
  285. {
  286. int max = OutBarCtrl::getMaxVisibleItem();
  287. if (onlineOnly) {
  288. for (; max >= 0; --max) {
  289. if (contact(max)->status != STATUS_OFFLINE)
  290. break;
  291. }
  292. }
  293. return max;
  294. }
  295. void MyICQCtrl::drawBackground(CDC *pDC, CRect &rc)
  296. {
  297. if (!skin) {
  298. OutBarCtrl::drawBackground(pDC, rc);
  299. return;
  300. }
  301. CBitmap &back = skin->bitmaps[SKIN_BACK];
  302. BITMAP bm;
  303. back.GetBitmap(&bm);
  304. CDC memDC;
  305. memDC.CreateCompatibleDC(pDC);
  306. CBitmap *oldBitmap = memDC.SelectObject(&back);
  307. for (int y = rc.top; y < rc.bottom; y += bm.bmHeight) {
  308. int h = bm.bmHeight;
  309. if (h > rc.bottom - y)
  310. h = rc.bottom - y;
  311. for (int x = rc.left; x < rc.right; x += bm.bmWidth) {
  312. int w = bm.bmWidth;
  313. if (w > rc.right - x)
  314. w = rc.right - x;
  315. pDC->BitBlt(x, y, w, h, &memDC, 0, 0, SRCCOPY);
  316. }
  317. }
  318. memDC.SelectObject(oldBitmap);
  319. }
  320. void MyICQCtrl::drawItemText(CDC *pDC, int i, COLORREF color)
  321. {
  322. OutBarCtrl::drawItemText(pDC, i,
  323. contact(i)->status == STATUS_AWAY ? RGB(0, 0, 255) : color);
  324. }
  325. void MyICQCtrl::drawFolder(CDC *pDC, int i, BOOL pressed, BOOL hilight)
  326. {
  327. if (!skin) {
  328. OutBarCtrl::drawFolder(pDC, i, pressed, hilight);
  329. return;
  330. }
  331. if (pressed)
  332. hilight = FALSE;
  333. CBitmap *bm = &skin->bitmaps[hilight ? SKIN_FOLDER_LIGHT : SKIN_FOLDER];
  334. CRect rc;
  335. getFolderRect(rc, i);
  336. int l = rc.left;
  337. int r = rc.right;
  338. CDC memDC;
  339. memDC.CreateCompatibleDC(pDC);
  340. CBitmap *oldBitmap = memDC.SelectObject(bm);
  341. BITMAP info;
  342. bm->GetBitmap(&info);
  343. pDC->BitBlt(l, rc.top, 40, info.bmHeight, &memDC, 0, 0, SRCCOPY);
  344. l += 40;
  345. r -= 40;
  346. pDC->BitBlt(r, rc.top, 40, info.bmHeight, &memDC, info.bmWidth - 40, 0, SRCCOPY);
  347. info.bmWidth -= 40 * 2;
  348. while (l < r) {
  349. int w = info.bmWidth;
  350. if (w > r - l)
  351. w = r - l;
  352. pDC->BitBlt(l, rc.top, w, info.bmHeight, &memDC, 40, 0, SRCCOPY);
  353. l += info.bmWidth;
  354. }
  355. memDC.SelectObject(oldBitmap);
  356. drawFolderText(pDC, i, rc);
  357. }
  358. void MyICQCtrl::drawScroll(CDC *pDC, int i, BOOL pressed)
  359. {
  360. if (!skin) {
  361. OutBarCtrl::drawScroll(pDC, i, pressed);
  362. return;
  363. }
  364. CBitmap *scroll;
  365. if (i == SCROLL_DIR_UP)
  366. scroll = &skin->bitmaps[pressed ? SKIN_SCROLLUP_PRESSED : SKIN_SCROLLUP];
  367. else
  368. scroll = &skin->bitmaps[pressed ? SKIN_SCROLLDOWN_PRESSED : SKIN_SCROLLDOWN];
  369. CDC memDC;
  370. memDC.CreateCompatibleDC(pDC);
  371. CBitmap *oldBitmap = memDC.SelectObject(scroll);
  372. CRect rc;
  373. getScrollRect(rc, i);
  374. BITMAP bm;
  375. scroll->GetBitmap(&bm);
  376. pDC->BitBlt(rc.left, rc.top, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);
  377. memDC.SelectObject(oldBitmap);
  378. }
  379. BEGIN_MESSAGE_MAP(MyICQCtrl, OutBarCtrl)
  380. //{{AFX_MSG_MAP(MyICQCtrl)
  381. ON_WM_TIMER()
  382. //}}AFX_MSG_MAP
  383. END_MESSAGE_MAP()
  384. /////////////////////////////////////////////////////////////////////////////
  385. // MyICQCtrl message handlers
  386. void MyICQCtrl::OnTimer(UINT nIDEvent) 
  387. {
  388. if (nIDEvent == IDT_BLINK_TEXT)
  389. doBlinkText();
  390. else if (nIDEvent == IDT_BLINK_IMAGE)
  391. doBlinkImage();
  392. else
  393. OutBarCtrl::OnTimer(nIDEvent);
  394. }