WndMessageListBox.cpp
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:30k
源码类别:

模拟服务器

开发平台:

C/C++

  1. // -------------------------------------------------------------------------
  2. // 文件名 : ShowChatText.cpp
  3. // 创建者 : 彭建波
  4. // 创建时间 : 2002-9-16 16:22:56
  5. // 功能描述 : 显示聊天内容
  6. // -------------------------------------------------------------------------
  7. #include "KWin32.h"
  8. #include "KIniFile.h"
  9. #include "WndMessage.h"
  10. #include "Wnds.h"
  11. #include "WndMessageListBox.h"
  12. #include "WndScrollBar.h"
  13. #include "../../../Engine/src/Text.h"
  14. #include "../../../Represent/iRepresent/iRepresentShell.h"
  15. #include "../../../Engine/Src/Text.h"
  16. extern iRepresentShell* g_pRepresentShell;
  17. #define MSGLISTBOX_S_SELABLE 0x00008000
  18. #define MSGLISTBOX_S_HIGHLIGHTABLE 0x00004000
  19. #define MSGLISTBOX_S_TEXTBOTTOM 0x00002000
  20. KWndMessageListBox::KWndMessageListBox()
  21. {
  22. m_pScrollbar = NULL;
  23. m_pMessages = NULL; //信息数据
  24. m_nNumMessage = 0; //信息条数目
  25. m_nCapability = 0; //信息条最多允许数目
  26. m_nFontSize = 12; //字体大小
  27. m_nNumMaxShowLine = 0;
  28. m_nNumBytesPerLine = 20; //每一行字符的数目
  29. m_nStartShowMsg = 0;
  30. m_nStartMsgSkipLine = 0;
  31. m_nNumVisibleTextLine = 0;
  32. m_nSelMsgIndex = -1;
  33. m_nHLMsgIndex  = -1;
  34. m_uTextLineShadowColor = 0;
  35. m_SelMsgBgColor = 0;
  36. m_bHitText = FALSE;
  37. m_nHideNumLine = 0;
  38. }
  39. // -------------------------------------------------------------------------
  40. // 功能 : 析构函数
  41. // -------------------------------------------------------------------------
  42. KWndMessageListBox::~KWndMessageListBox()
  43. {
  44. SetCapability(0);
  45. }
  46. // -------------------------------------------------------------------------
  47. // 功能 : 设置可以容纳讯息的数目
  48. // -------------------------------------------------------------------------
  49. int KWndMessageListBox::SetCapability(int nNumMessage)
  50. {
  51. KOneMsgInfo** pNew = NULL;
  52. if (nNumMessage)
  53. {
  54. pNew = (KOneMsgInfo**)malloc(sizeof(KOneMsgInfo*) * nNumMessage);
  55. if (pNew == NULL)
  56. return false;
  57. memset(pNew, 0, sizeof(KOneMsgInfo*) * nNumMessage);
  58. }
  59. if (nNumMessage && m_nNumMessage)
  60. {
  61. if (m_nNumMessage <= nNumMessage)
  62. {
  63. memcpy(pNew, m_pMessages, sizeof(KOneMsgInfo*) * m_nNumMessage);
  64. memset(m_pMessages, 0, sizeof(KOneMsgInfo*) * m_nNumMessage);
  65. }
  66. else
  67. {
  68. memcpy(pNew, &m_pMessages[m_nNumMessage - nNumMessage], sizeof(KOneMsgInfo*) * nNumMessage);
  69. memset(&m_pMessages[m_nNumMessage - nNumMessage], 0, sizeof(KOneMsgInfo*) * nNumMessage);
  70. m_nNumMessage = nNumMessage;
  71. }
  72. }
  73. else
  74. m_nNumMessage = 0;
  75. if (m_pMessages)
  76. {
  77. for (int i = 0; i < m_nCapability; i++)
  78. {
  79. if (m_pMessages[i])
  80. {
  81. free(m_pMessages[i]);
  82. m_pMessages[i] = NULL;
  83. }
  84. }
  85. free(m_pMessages);
  86. m_pMessages = NULL;
  87. }
  88. m_pMessages = pNew;
  89. m_nCapability = nNumMessage;
  90. UpdateData();
  91. return true;
  92. }
  93. // -------------------------------------------------------------------------
  94. // 功能 : 设置关联滚动条
  95. // -------------------------------------------------------------------------
  96. void KWndMessageListBox::SetScrollbar(KWndScrollBar* pScroll)
  97. {
  98. if (m_pScrollbar = pScroll)
  99. UpdateData();
  100. }
  101. // -------------------------------------------------------------------------
  102. // 功能 : 新添一条信息
  103. // -------------------------------------------------------------------------
  104. int KWndMessageListBox::AddOneMessage(const char* pText, int nLen, unsigned int uTextBKColor)
  105. {
  106. if (pText == NULL)
  107. return 0;
  108. if (nLen < 0)
  109. nLen = strlen(pText);
  110. if (m_nCapability > 0 && nLen)
  111. {
  112. ClearHideLine();
  113. int nTo = GetItemLineCount(m_nNumMessage);
  114. int nStart = GetItemLineCount(m_nStartShowMsg) + m_nStartMsgSkipLine;
  115. if (m_nNumMessage == m_nCapability)
  116. {
  117. KOneMsgInfo* pMsg = m_pMessages[0];
  118. memmove(&m_pMessages[0], &m_pMessages[1],
  119. sizeof(KOneMsgInfo*) * (m_nNumMessage - 1));
  120. m_nNumMessage--;
  121. m_pMessages[m_nNumMessage] = pMsg;
  122. }
  123. KOneMsgInfo* pMsg = m_pMessages[m_nNumMessage];
  124. if (pMsg == NULL || pMsg->nMaxSize < nLen || pMsg->nMaxSize - nLen > 256)
  125. {
  126. pMsg = (KOneMsgInfo*)realloc(pMsg, sizeof(KOneMsgInfo) + nLen);
  127. if (pMsg == NULL)
  128. return false;
  129. m_pMessages[m_nNumMessage] = pMsg;
  130. pMsg->nMaxSize = nLen;
  131. }
  132. memcpy(pMsg->Msg, pText, nLen);
  133. pMsg->Msg[nLen] = 0;
  134. pMsg->nLen = nLen;
  135. pMsg->uTextBKColor = uTextBKColor;
  136. if (g_pRepresentShell)
  137. {
  138. pMsg->nLines = TGetEncodedTextLineCount(
  139. pMsg->Msg, nLen, m_nNumBytesPerLine, pMsg->nCharWidth, m_nFontSize, 0, 0, true);
  140. }
  141. else
  142. {
  143. pMsg->nLines = 0;
  144. pMsg->nCharWidth = 0;
  145. }
  146. m_nNumMessage++;
  147. int nTo2 = GetItemLineCount(m_nNumMessage);
  148. if (nTo > 0)
  149. SetFirstShowLine(MulDiv(nStart, nTo2, nTo));
  150. UpdateData();
  151. return true;
  152. }
  153. return false;
  154. }
  155. // -------------------------------------------------------------------------
  156. // 功能 : 删除一条消息
  157. // -------------------------------------------------------------------------
  158. void KWndMessageListBox::RemoveAMessage(int nIndex)
  159. {
  160. if (nIndex >= 0 && nIndex < m_nNumMessage)
  161. {
  162. ClearHideLine();
  163. if (m_nSelMsgIndex <= nIndex)
  164. m_nSelMsgIndex = -1;
  165. else
  166. m_nSelMsgIndex--;
  167. m_nHLMsgIndex = -1;
  168. int nTo = GetItemLineCount(m_nNumMessage);
  169. int nStart = GetItemLineCount(m_nStartShowMsg) + m_nStartMsgSkipLine;
  170. KOneMsgInfo* pMsg = m_pMessages[nIndex];
  171. nStart -= pMsg->nLines;
  172. if (m_nNumMessage < m_nCapability)
  173. {
  174. memmove(&m_pMessages[nIndex], &m_pMessages[nIndex + 1],
  175. sizeof(KOneMsgInfo*) * (m_nNumMessage - nIndex));
  176. m_nNumMessage--;
  177. m_pMessages[m_nNumMessage] = pMsg;
  178. }
  179. else
  180. m_nNumMessage--;
  181. int nTo2 = GetItemLineCount(m_nNumMessage);
  182. if (nTo > 0)
  183. SetFirstShowLine(MulDiv(nStart, nTo2, nTo));
  184. UpdateData();
  185. }
  186. }
  187. // -------------------------------------------------------------------------
  188. // 功能 : 删除全部消息
  189. // -------------------------------------------------------------------------
  190. void KWndMessageListBox::Clear()
  191. {
  192. m_nNumMessage = 0;
  193. m_nNumVisibleTextLine = 0;
  194. m_nSelMsgIndex = -1;
  195. m_nHLMsgIndex = -1;
  196. m_nStartShowMsg = 0;
  197. m_nStartMsgSkipLine = 0;
  198. if (m_pScrollbar)
  199. {
  200. m_pScrollbar->SetScrollPos(0);
  201. m_pScrollbar->SetValueRange(0, 0);
  202. }
  203. }
  204. void KWndMessageListBox::Clone(KWndMessageListBox* pCopy)
  205. {
  206. if (pCopy)
  207. {
  208. KWndWindow::Clone(pCopy);
  209. pCopy->m_nFontSize = m_nFontSize;
  210. pCopy->m_nNumBytesPerLine = m_nNumBytesPerLine;
  211. pCopy->m_nNumMaxShowLine = m_nNumMaxShowLine;
  212. pCopy->m_MsgColor = m_MsgColor;
  213. pCopy->m_MsgBorderColor = m_MsgBorderColor;
  214. pCopy->m_SelMsgColor = m_SelMsgColor;
  215. pCopy->m_SelMsgBorderColor = m_SelMsgBorderColor;
  216. pCopy->m_SelMsgBgColor = m_SelMsgBgColor;
  217. pCopy->m_HLMsgColor = m_HLMsgColor;
  218. pCopy->m_HLMsgBorderColor = m_HLMsgBorderColor;
  219. pCopy->m_uTextLineShadowColor = m_uTextLineShadowColor;
  220. pCopy->SetCapability(m_nCapability);
  221. }
  222. }
  223. // -------------------------------------------------------------------------
  224. // 功能 : 初始化
  225. // -------------------------------------------------------------------------
  226. int KWndMessageListBox::Init(KIniFile* pIniFile, const char* pSection)
  227. {
  228. if (KWndWindow::Init(pIniFile, pSection))
  229. {
  230. int nValue;
  231. pIniFile->GetInteger(pSection, "MaxMsgCount", 16, &nValue);
  232. SetCapability(nValue);
  233. pIniFile->GetInteger(pSection, "HitText", 0, &m_bHitText);
  234. //====文字大小====
  235. pIniFile->GetInteger(pSection, "Font", 16, &m_nFontSize);
  236. if (m_nFontSize < 4)
  237. m_nFontSize = 4;
  238. //---文字显示宽度与行数---
  239. m_nNumBytesPerLine = (m_Width * 2) / m_nFontSize;
  240. if (m_nNumBytesPerLine < 2)
  241. m_nNumBytesPerLine = 2;
  242. m_nNumMaxShowLine = m_Height / (m_nFontSize + 1);
  243. char Buff[16];
  244. pIniFile->GetString(pSection, "MsgColor", "", Buff, 16);
  245. m_MsgColor = GetColor(Buff);
  246. pIniFile->GetString(pSection, "MsgBorderColor", "", Buff, 16);
  247. m_MsgBorderColor = GetColor(Buff);
  248. char Buffer[32];
  249. if (pIniFile->GetString(pSection, "TextLineShadow", "", Buffer, sizeof(Buffer)))
  250. {
  251. m_uTextLineShadowColor = (GetColor(Buffer) & 0xffffff);
  252. pIniFile->GetInteger(pSection, "TextLineShadowAlpha", 128, &nValue);
  253. if (nValue > 255 || nValue < 0)
  254. m_uTextLineShadowColor |= 0x16000000;
  255. else
  256. m_uTextLineShadowColor |= (((255 - nValue) << 21) & 0xff000000);
  257. }
  258. else
  259. m_uTextLineShadowColor = 0;
  260. pIniFile->GetInteger(pSection, "Selable", 0, &nValue);
  261. if (nValue)
  262. {
  263. m_Style |= MSGLISTBOX_S_SELABLE;
  264. pIniFile->GetString(pSection, "SelColor", "", Buff, 16);
  265. m_SelMsgColor = GetColor(Buff);
  266. pIniFile->GetString(pSection, "SelBorderColor", "", Buff, 16);
  267. m_SelMsgBorderColor = GetColor(Buff);
  268. if (pIniFile->GetString(pSection, "SelBgColor", "", Buffer, sizeof(Buffer)))
  269. {
  270. m_SelMsgBgColor = (GetColor(Buffer) & 0xffffff);
  271. pIniFile->GetInteger(pSection, "SelBgColorAlpha", 128, &nValue);
  272. if (nValue > 255 || nValue < 0)
  273. m_SelMsgBgColor |= 0x16000000;
  274. else
  275. m_SelMsgBgColor |= (((255 - nValue) << 21) & 0xff000000);
  276. }
  277. else
  278. m_SelMsgBgColor = 0;
  279. pIniFile->GetInteger(pSection, "HighLight", 0, &nValue);
  280. if (nValue)
  281. {
  282. m_Style |= MSGLISTBOX_S_HIGHLIGHTABLE;
  283. pIniFile->GetString(pSection, "HighLightColor", "", Buff, 16);
  284. m_HLMsgColor = GetColor(Buff);
  285. pIniFile->GetString(pSection, "HighLightBorderColor", "", Buff, 16);
  286. m_HLMsgBorderColor = GetColor(Buff);
  287. }
  288. else
  289. {
  290. m_nHLMsgIndex = -1;
  291. m_Style &= ~MSGLISTBOX_S_HIGHLIGHTABLE;
  292. }
  293. }
  294. else
  295. {
  296. m_nSelMsgIndex = -1;
  297. m_nHLMsgIndex = -1;
  298. m_Style &= ~(MSGLISTBOX_S_SELABLE | MSGLISTBOX_S_HIGHLIGHTABLE);
  299. }
  300. pIniFile->GetInteger(pSection, "TextBottom", 0, &nValue);
  301. if (nValue)
  302. m_Style |= MSGLISTBOX_S_TEXTBOTTOM;
  303. else
  304. m_Style &= ~MSGLISTBOX_S_TEXTBOTTOM;
  305. UpdateData();
  306. return true;
  307. }
  308. return false;
  309. }
  310. //设置窗口大小
  311. void KWndMessageListBox::SetSize(int nWidth, int nHeight)
  312. {
  313. ClearHideLine();
  314. if (nWidth < m_nFontSize)
  315. nWidth = m_nFontSize + 1;
  316. if (nHeight < m_nFontSize)
  317. nHeight = m_nFontSize + 1;
  318. KWndWindow::SetSize(nWidth, nHeight);
  319. //---文字显示宽度与行数---
  320. int nNumBytesPerLine = (m_Width * 2) / m_nFontSize;
  321. if (nNumBytesPerLine < 2)
  322. nNumBytesPerLine = 2;
  323. int nLines = m_Height / (m_nFontSize + 1);
  324. if (nLines != m_nNumMaxShowLine || m_nNumBytesPerLine != nNumBytesPerLine)
  325. {
  326. int nTo = 0;
  327. if (m_Style & MSGLISTBOX_S_TEXTBOTTOM)
  328. {
  329. nTo  = GetItemLineCount(m_nNumMessage) - GetItemLineCount(m_nStartShowMsg) - m_nStartMsgSkipLine - m_nNumMaxShowLine;
  330. nTo = max(nTo, 0);
  331. }
  332. m_nNumMaxShowLine = nLines;
  333. m_nNumBytesPerLine = nNumBytesPerLine;
  334. for (int i = 0; i < m_nNumMessage; i++)
  335. {
  336. if (g_pRepresentShell)
  337. {
  338. m_pMessages[i]->nLines = TGetEncodedTextLineCount(
  339. m_pMessages[i]->Msg, m_pMessages[i]->nLen, m_nNumBytesPerLine, m_pMessages[i]->nCharWidth, m_nFontSize, 0, 0, true);
  340. }
  341. else
  342. m_pMessages[i]->nLines = 0;
  343. }
  344. if (m_Style & MSGLISTBOX_S_TEXTBOTTOM)
  345. SetFirstShowLine(GetItemLineCount(m_nNumMessage) - nTo - m_nNumMaxShowLine);
  346. UpdateData();
  347. }
  348. }
  349. void KWndMessageListBox::SetFontSize(int nFontSize)
  350. {
  351. if (nFontSize < 12 || nFontSize > 16)
  352. return;
  353. if (m_nFontSize == nFontSize)
  354. return;
  355. m_nFontSize = nFontSize;
  356. SetSize(m_Width, m_Height);
  357. }
  358. // -------------------------------------------------------------------------
  359. // 功能 : 根据内容增删或者窗口尺寸变化重新作些参数计算以及滚动条容量调整
  360. // -------------------------------------------------------------------------
  361. void KWndMessageListBox::UpdateData()
  362. {
  363. int nTotalLine = 0;
  364. for (int i = 0; i < m_nNumMessage; i++)
  365. nTotalLine += m_pMessages[i]->nLines;
  366. if (nTotalLine > m_nNumMaxShowLine)
  367. {
  368. if (m_pScrollbar)
  369. {
  370. m_pScrollbar->Enable(true);
  371. m_pScrollbar->SetValueRange(0, nTotalLine - m_nNumMaxShowLine);
  372. }
  373. m_nNumVisibleTextLine = m_nNumMaxShowLine;
  374. }
  375. else
  376. {
  377. if (m_pScrollbar)
  378. {
  379. m_pScrollbar->Enable(false);
  380. m_pScrollbar->SetValueRange(0, 0);
  381. }
  382. m_nNumVisibleTextLine = nTotalLine;
  383. }
  384. }
  385. // -------------------------------------------------------------------------
  386. // 功能 : 获取第一条被显示的文字是全部文字的第几行
  387. // -------------------------------------------------------------------------
  388. int KWndMessageListBox::GetFirstShowLine()
  389. {
  390. int nLine = 0;
  391. for (int i = 0; i < m_nStartShowMsg; i++)
  392. nLine += m_pMessages[i]->nLines;
  393. return (nLine + m_nStartMsgSkipLine);
  394. }
  395. // -------------------------------------------------------------------------
  396. // 功能 : 设置第一条被显示的文字是全部文字的第几行
  397. // -------------------------------------------------------------------------
  398. void KWndMessageListBox::SetFirstShowLine(int nLine)
  399. {
  400. ClearHideLine();
  401. if (nLine <= 0)
  402. {
  403. m_nStartShowMsg = 0;
  404. m_nStartMsgSkipLine = 0;
  405. return;
  406. }
  407. m_nStartMsgSkipLine = nLine;
  408. m_nStartShowMsg = 0;
  409. while (m_nStartShowMsg < m_nNumMessage)
  410. {
  411. if (m_pMessages[m_nStartShowMsg]->nLines < m_nStartMsgSkipLine)
  412. {
  413. m_nStartMsgSkipLine -= m_pMessages[m_nStartShowMsg]->nLines;
  414. m_nStartShowMsg++;
  415. continue;
  416. }
  417. if (m_pMessages[m_nStartShowMsg]->nLines == m_nStartMsgSkipLine)
  418. {
  419. m_nStartMsgSkipLine = 0;
  420. m_nStartShowMsg++;
  421. }
  422. break;
  423. }
  424. m_nNumVisibleTextLine = 0;
  425. int nMsg = m_nStartShowMsg;
  426. if (nMsg < m_nNumMessage)
  427. {
  428. m_nNumVisibleTextLine += m_pMessages[nMsg]->nLines - m_nStartMsgSkipLine;
  429. nMsg++;
  430. for (; nMsg < m_nNumMessage; nMsg++)
  431. m_nNumVisibleTextLine += m_pMessages[nMsg]->nLines;
  432. if (m_nNumVisibleTextLine >= m_nNumMaxShowLine)
  433. m_nNumVisibleTextLine = m_nNumMaxShowLine;
  434. }
  435. }
  436. int KWndMessageListBox::GetItemLineCount(int nIndex)
  437. {
  438. int nLine = 0;
  439. for (int i = min(nIndex, m_nNumMessage) - 1; i >= 0; i--)
  440. nLine += m_pMessages[i]->nLines;
  441. return nLine;
  442. }
  443. // -------------------------------------------------------------------------
  444. // 功能 : 绘制窗口
  445. // -------------------------------------------------------------------------
  446. void KWndMessageListBox::PaintWindow()
  447. {
  448. KWndWindow::PaintWindow();
  449. if (g_pRepresentShell == NULL || m_nNumMessage == 0)
  450. return;
  451. if (m_nHideNumLine >= m_nNumMaxShowLine)//完全隐藏了,就不用画了
  452. return;
  453. if (m_nHideNumLine >= m_nNumVisibleTextLine) //可见字完全隐藏了,就不用画了
  454. return;
  455. int nCurMsg = m_nStartShowMsg;
  456. int nViewLines = m_nNumMaxShowLine;
  457. int nSkipLine = m_nStartMsgSkipLine;
  458. int nNumVisibleTextLine = 0;
  459. int y = m_nAbsoluteTop + GetOffsetTextHeight();
  460. if (m_Style & MSGLISTBOX_S_TEXTBOTTOM)
  461. {
  462. nNumVisibleTextLine = m_nNumVisibleTextLine - m_nHideNumLine;
  463. y += m_nHideNumLine * (m_nFontSize + 1);
  464. }
  465. else
  466. {
  467. nNumVisibleTextLine = m_nNumVisibleTextLine - m_nHideNumLine;
  468. }
  469. KRUShadow bg;
  470. if (m_uTextLineShadowColor)
  471. {
  472. bg.Color.Color_dw = m_uTextLineShadowColor;
  473. bg.oPosition.nX = m_nAbsoluteLeft;
  474. bg.oEndPos.nX = bg.oPosition.nX + m_Width;
  475. bg.oPosition.nY = y;
  476. bg.oEndPos.nY = bg.oPosition.nY + nNumVisibleTextLine * (m_nFontSize + 1);
  477. g_pRepresentShell->DrawPrimitives(1, &bg, RU_T_SHADOW, true);
  478. }
  479. while (nViewLines > 0 && nCurMsg < m_nNumMessage)
  480. {
  481. KOneMsgInfo* pCurMsg = m_pMessages[nCurMsg];
  482. KOutputTextParam Param;
  483. Param.nSkipLine = nSkipLine;
  484. Param.nNumLine = pCurMsg->nLines - nSkipLine;
  485. if (Param.nNumLine > nViewLines)
  486. Param.nNumLine = nViewLines;
  487. Param.nX = m_nAbsoluteLeft;
  488. Param.nY = y;
  489. Param.nZ = TEXT_IN_SINGLE_PLANE_COORD;
  490. int nOffset = 0;
  491. bool bDraw = (nViewLines + m_nHideNumLine <= m_nNumMaxShowLine);
  492. if (bDraw)
  493. {
  494. if (nCurMsg == m_nSelMsgIndex && (m_Style & MSGLISTBOX_S_SELABLE))
  495. {
  496. //绘制背景色
  497. if (m_SelMsgBgColor)
  498. {
  499. bg.Color.Color_dw = m_SelMsgBgColor;
  500. bg.oPosition.nX = Param.nX;
  501. bg.oPosition.nY = Param.nY;
  502. bg.oEndPos.nX = bg.oPosition.nX + m_Width;
  503. bg.oEndPos.nY = bg.oPosition.nY + Param.nNumLine * (m_nFontSize + 1);
  504. g_pRepresentShell->DrawPrimitives(1, &bg, RU_T_SHADOW, true);
  505. }
  506. Param.Color = m_SelMsgColor;
  507. Param.BorderColor = m_SelMsgBorderColor;
  508. }
  509. else if (nCurMsg == m_nHLMsgIndex)
  510. {
  511. Param.Color = m_HLMsgColor;
  512. Param.BorderColor = m_HLMsgBorderColor;
  513. }
  514. else
  515. {
  516. Param.Color = m_MsgColor;
  517. Param.BorderColor = m_MsgBorderColor;
  518. //nOffset = TSplitString(pCurMsg->Msg, 5, false);
  519. }
  520. if (pCurMsg->uTextBKColor) //绘制文字衬底
  521. {
  522. bg.Color.Color_dw = pCurMsg->uTextBKColor;
  523. bg.oPosition.nX = Param.nX;
  524. bg.oPosition.nY = Param.nY;
  525. bg.oEndPos.nX = bg.oPosition.nX + (pCurMsg->nCharWidth * m_nFontSize / 2);
  526. bg.oEndPos.nY = bg.oPosition.nY + Param.nNumLine * (m_nFontSize + 1);
  527. g_pRepresentShell->DrawPrimitives(1, &bg, RU_T_SHADOW, true);
  528. }
  529. Param.bPicPackInSingleLine = true;
  530. g_pRepresentShell->OutputRichText(m_nFontSize, &Param, pCurMsg->Msg + nOffset, pCurMsg->nLen - nOffset, m_Width);
  531. y += Param.nNumLine * (m_nFontSize + 1);
  532. }
  533. nSkipLine = 0;
  534. nViewLines -= Param.nNumLine;
  535. nCurMsg++;
  536. }
  537. }
  538. //--------------------------------------------------------------------------
  539. // 功能:窗口函数
  540. //--------------------------------------------------------------------------
  541. int KWndMessageListBox::WndProc(unsigned int uMsg, unsigned int uParam, int nParam)
  542. {
  543. switch(uMsg)
  544. {
  545. case WM_MOUSEMOVE:
  546. if (m_Style & MSGLISTBOX_S_HIGHLIGHTABLE)
  547. OnMouseMove(LOWORD(nParam), HIWORD(nParam));
  548. break;
  549. case WM_LBUTTONDOWN:
  550. if (m_Style & MSGLISTBOX_S_SELABLE)
  551. OnLButtonDown(LOWORD(nParam), HIWORD(nParam));
  552. break;
  553. case WM_LBUTTONDBLCLK:
  554. if (m_Style & MSGLISTBOX_S_SELABLE)
  555. OnLButtonDClick(LOWORD(nParam), HIWORD(nParam));
  556. break;
  557. case WM_MOUSEWHEEL:
  558. {
  559. if (m_pScrollbar && !m_pScrollbar->IsDisable())
  560. {
  561. int zDelta = short(HIWORD(uParam));
  562. int nPos = m_pScrollbar->GetScrollPos();
  563. nPos += (-zDelta / WHEEL_DELTA);
  564. m_pScrollbar->SetScrollPos(nPos);
  565. }
  566. }
  567. break;
  568. default:
  569. return KWndWindow::WndProc(uMsg, uParam, nParam);
  570. }
  571. return 0;
  572. }
  573. int KWndMessageListBox::GetMsgAtPoint(int x, int y)
  574. {
  575. int nSelLine = 0;
  576. nSelLine = (y - m_nAbsoluteTop - GetOffsetTextHeight()) / (m_nFontSize + 1);
  577. if (nSelLine < 0 || nSelLine >= m_nNumVisibleTextLine)
  578. return -1;
  579. int nMsg = m_nStartShowMsg;
  580. int nViewLine = m_nNumMaxShowLine;
  581. int nSkipLine = m_nStartMsgSkipLine;
  582. int nNumLine = 0;
  583. while (nViewLine > 0 && nMsg < m_nNumMessage)
  584. {
  585. KOneMsgInfo* pCurMsg = m_pMessages[nMsg];
  586. nNumLine += pCurMsg->nLines - nSkipLine;
  587. if (nNumLine > nViewLine)
  588. {
  589. if (nSelLine < nViewLine)
  590. return nMsg;
  591. break;
  592. }
  593. if (nSelLine < nNumLine)
  594. return nMsg;
  595. nSkipLine = 0;
  596. nMsg++;
  597. }
  598. return -1;
  599. }
  600. int KWndMessageListBox::HitTextAtPoint(int x, int y)
  601. {
  602. int n = GetMsgAtPoint(x, y);
  603. if (n >= 0 && n < m_nNumMessage)
  604. {
  605. if (m_bHitText)
  606. {
  607. x -= m_nAbsoluteLeft;
  608. if (x > 0 && x <= (m_pMessages[n]->nCharWidth / 2 * m_nFontSize))
  609. {
  610. int nPos = TFindSpecialCtrlInEncodedText(m_pMessages[n]->Msg, 
  611. m_pMessages[n]->nLen, 0, ':');
  612. if (nPos >= 0)
  613. {
  614. int nNameLen = 0;
  615. TGetEncodedTextLineCount(m_pMessages[n]->Msg, nPos, m_nNumBytesPerLine,
  616. nNameLen, m_nFontSize, 0, 0, true);
  617. if (x <= (nNameLen  * m_nFontSize / 2))
  618. {
  619. return n;
  620. }
  621. }
  622. }
  623. }
  624. else
  625. return n;
  626. }
  627. return -1;
  628. }
  629. //--------------------------------------------------------------------------
  630. // 功能:响应鼠标左键在此按下
  631. //--------------------------------------------------------------------------
  632. void KWndMessageListBox::OnLButtonDown(int x, int y)
  633. {
  634. int nSel = HitTextAtPoint(x, y);
  635. if (nSel >= 0 && m_pParentWnd)
  636. m_pParentWnd->WndProc(WND_N_LIST_ITEM_ACTIVE, (unsigned int)(KWndWindow*)this, m_nSelMsgIndex);
  637. SetCurSel(nSel);
  638. }
  639. //响应鼠标左键double click
  640. void KWndMessageListBox::OnLButtonDClick(int x, int y)
  641. {
  642. int nSel = HitTextAtPoint(x, y);
  643. if (nSel >= 0 && m_pParentWnd)
  644. {
  645. m_pParentWnd->WndProc(WND_N_LIST_ITEM_D_CLICK,
  646. (unsigned int)(KWndWindow*)this, nSel);
  647. }
  648. }
  649. int KWndMessageListBox::SetCurSel(int nIndex)
  650. {
  651. ClearHideLine();
  652. if (nIndex != m_nSelMsgIndex)
  653. {
  654. m_nSelMsgIndex = nIndex;
  655. }
  656. if (m_pParentWnd)
  657. m_pParentWnd->WndProc(WND_N_LIST_ITEM_SEL, (unsigned int)(KWndWindow*)this, m_nSelMsgIndex);
  658. return m_nSelMsgIndex;
  659. }
  660. //--------------------------------------------------------------------------
  661. // 功能:响应鼠标移动
  662. //--------------------------------------------------------------------------
  663. void KWndMessageListBox::OnMouseMove(int x, int y)
  664. {
  665. int nSel = HitTextAtPoint(x, y);
  666. if (nSel != m_nHLMsgIndex)
  667. {
  668. m_nHLMsgIndex = nSel;
  669. if (m_pParentWnd)
  670. {
  671. m_pParentWnd->WndProc(WND_N_LIST_ITEM_HIGHLIGHT, (unsigned int)(KWndWindow*)this, m_nHLMsgIndex);
  672. }
  673. }
  674. }
  675. //--------------------------------------------------------------------------
  676. // 功能:获取一条信息的内容
  677. //  参数:nIndex  --> 信息的索引,如果值小余0,则-n(n>0)表示倒数第n条信息
  678. //        pBuffer --> 接受信息内容的缓冲区
  679. //        nLen    --> pBuffer所指缓冲区的大小
  680. //        bExcludeCtrl --> 是否去除信息中的控制符
  681. //  返回:如果返回值>=0表示取得了指定的信息的内容,返回值为存到pBuffer缓冲区中信息的长度
  682. //        如果返回值<0表示操作失败,原因可能为不存在指定索引的信息条目,或者缓冲区大小不足等原因。
  683. //--------------------------------------------------------------------------
  684. int KWndMessageListBox::GetOneMessage(int nIndex, char* pBuffer, int nLen, bool bExcludeCtrl)
  685. {
  686. if (pBuffer)
  687. {
  688. if (nIndex < 0)
  689. nIndex = m_nNumMessage + nIndex;
  690. if (nIndex >= 0 && nIndex < m_nNumMessage)
  691. {
  692. int nReturn = m_pMessages[nIndex]->nLen;
  693. if (nLen >= nReturn)
  694. {
  695. memcpy(pBuffer, m_pMessages[nIndex]->Msg, nReturn);
  696. if (bExcludeCtrl)
  697. nReturn = TRemoveCtrlInEncodedText(pBuffer, nReturn);
  698. if (nLen > nReturn)
  699. pBuffer[nReturn] = 0;
  700. return nReturn;
  701. }
  702. }
  703. }
  704. return -1;
  705. }
  706. //--------------------------------------------------------------------------
  707. // 功能:从窗口分离出数据
  708. // 返回:窗口的数据的句柄。
  709. // 备注:此返回句柄,后续必须调用BindData使它被设置回窗口或调用FreeData释放它,
  710. // 否则会造成内存的泄漏。
  711. //--------------------------------------------------------------------------
  712. unsigned int KWndMessageListBox::SplitData()
  713. {
  714. KMessageListData* pData = NULL;
  715. if (m_nCapability)
  716. {
  717. pData = (KMessageListData*)malloc(sizeof(KMessageListData));
  718. if (pData)
  719. {
  720. pData->nCapability = m_nCapability;
  721. pData->nNumMessage = m_nNumMessage;
  722. pData->nSelMsgIndex = m_nSelMsgIndex;
  723. pData->nStartMsgSkipLine = m_nStartMsgSkipLine;
  724. pData->nStartShowMsg = m_nStartShowMsg;
  725. pData->pMessages = m_pMessages;
  726. m_nNumMessage = 0;
  727. m_nSelMsgIndex = -1;
  728. m_nStartMsgSkipLine = 0;
  729. m_nStartShowMsg = 0;
  730. m_pMessages = (KOneMsgInfo**)malloc(sizeof(KOneMsgInfo*) * m_nCapability);
  731. if (m_pMessages)
  732. memset(m_pMessages, 0, sizeof(KOneMsgInfo*) * m_nCapability);
  733. else
  734. m_nCapability = 0;
  735. if (m_pScrollbar)
  736. {
  737. m_pScrollbar->Enable(false);
  738. m_pScrollbar->SetScrollPos(0);
  739. }
  740. }
  741. }
  742. return ((unsigned int)pData);
  743. }
  744. //--------------------------------------------------------------------------
  745. // 功能:给窗口捆绑数据
  746. //  参数:hData --> 要捆绑到窗口的数据的句柄,此句柄为之前调用SplitData或
  747. // BindData函数获得的返回值。
  748. // 返回:捆绑操作之前,窗口的数据的句柄。
  749. // 备注:此返回句柄,后续必须调用BindData使它被设置回窗口或调用FreeData释放它,
  750. // 否则会造成内存的泄漏。
  751. //--------------------------------------------------------------------------
  752. unsigned int KWndMessageListBox::BindData(unsigned int hData)
  753. {
  754. if (hData == NULL)
  755. return SplitData();
  756. KMessageListData* pData = (KMessageListData*)hData;
  757. KMessageListData NewData = *pData;
  758. pData->nCapability = m_nCapability;
  759. pData->nNumMessage = m_nNumMessage;
  760. pData->nSelMsgIndex = m_nSelMsgIndex;
  761. pData->nStartMsgSkipLine = m_nStartMsgSkipLine;
  762. pData->nStartShowMsg = m_nStartShowMsg;
  763. pData->pMessages = m_pMessages;
  764. m_nCapability = NewData.nCapability;
  765. m_nNumMessage = NewData.nNumMessage;
  766. m_nSelMsgIndex = NewData.nSelMsgIndex;
  767. m_nStartMsgSkipLine = NewData.nStartMsgSkipLine;
  768. m_nStartShowMsg = NewData.nStartShowMsg;
  769. m_pMessages = NewData.pMessages;
  770. if (m_pScrollbar)
  771. {
  772. int i, nTotalLine = 0;
  773. for(i = 0; i < m_nStartShowMsg; i++)
  774. nTotalLine += m_pMessages[i]->nLines;
  775. int nFirstLine = nTotalLine + m_nStartMsgSkipLine;
  776. for (;i < m_nNumMessage; i++)
  777. nTotalLine += m_pMessages[i]->nLines;
  778. if (nTotalLine > m_nNumMaxShowLine)
  779. {
  780. m_nNumVisibleTextLine = m_nNumMaxShowLine;
  781. m_pScrollbar->SetValueRange(0, nTotalLine - m_nNumMaxShowLine);
  782. m_pScrollbar->SetScrollPos(nFirstLine);
  783. m_pScrollbar->Enable(true);
  784. }
  785. else
  786. {
  787. m_nNumVisibleTextLine = nTotalLine;
  788. m_pScrollbar->Enable(false);
  789. m_pScrollbar->SetScrollPos(0);
  790. }
  791. }
  792. return hData;
  793. }
  794. //--------------------------------------------------------------------------
  795. // 功能:释放窗口数据句柄
  796. //  参数:hData --> 要释放的窗口的数据的句柄,此句柄为之前调用SplitData或
  797. // BindData函数获得的返回值。
  798. //--------------------------------------------------------------------------
  799. void KWndMessageListBox::FreeData(unsigned int hData)
  800. {
  801. if (hData)
  802. {
  803. if (((KMessageListData*)hData)->pMessages)
  804. free (((KMessageListData*)hData)->pMessages);
  805. free ((void*)hData);
  806. }
  807. }
  808. unsigned int KWndMessageListBox::GetOffsetTextHeight()
  809. {
  810. if (m_Style & MSGLISTBOX_S_TEXTBOTTOM)
  811. {
  812. if (m_nNumVisibleTextLine < m_nNumMaxShowLine)
  813. return (m_nNumMaxShowLine - m_nNumVisibleTextLine) * (m_nFontSize + 1);
  814. }
  815. return 0;
  816. }
  817. int KWndMessageListBox::PtInWindow(int x, int y)
  818. {
  819. if (m_bHitText)
  820. {
  821. if (HitTextAtPoint(x, y) >= 0)
  822. return 1;
  823. else
  824. return 0;
  825. }
  826. else
  827. return KWndWindow::PtInWindow(x, y);
  828. }
  829. void KWndMessageListBox::ClearHideLine()
  830. {
  831. m_nHideNumLine = 0;
  832. }
  833. void KWndMessageListBox::HideNextLine()
  834. {
  835. int nCurMsg = m_nStartShowMsg;
  836. if (m_pMessages && m_nHideNumLine < m_nNumMaxShowLine && m_nNumMessage > 0 && nCurMsg < m_nNumMessage)
  837. {
  838. int nNewHideNumLine = m_pMessages[nCurMsg]->nLines - m_nStartMsgSkipLine;
  839. while (nNewHideNumLine <= m_nHideNumLine)
  840. {
  841. nCurMsg++;
  842. if (nCurMsg < m_nNumMessage)
  843. {
  844. nNewHideNumLine += m_pMessages[nCurMsg]->nLines;
  845. }
  846. else
  847. break;
  848. }
  849. m_nHideNumLine = min(nNewHideNumLine, m_nNumMaxShowLine);
  850. }
  851. }
  852. void KWndMessageListBox::HideAllLine()
  853. {
  854. m_nHideNumLine = m_nNumMaxShowLine;
  855. }
  856. int KWndMessageListBox::GetMinHeight()
  857. {
  858. return max(m_nFontSize + 1, 0);
  859. }
  860. /////////////////////////////////////////////////////////////////////////////////
  861. /////////////////////////////////////////////////////////////////////////////////
  862. KScrollMessageListBox::KScrollMessageListBox()
  863. {
  864. m_nMinLineCount = 2;
  865. m_nMaxLineCount = 30;
  866. m_nCurrentLineCount = 0;
  867. m_nLineHeight = 12;
  868. AddChild(&m_MsgList);
  869. AddChild(&m_Scroll);
  870. }
  871. int KScrollMessageListBox::Init(KIniFile* pIniFile, const char* pSection)//初始化
  872. {
  873. if (KWndWindow::Init(pIniFile, pSection))
  874. {
  875. char Buffer[128];
  876. sprintf(Buffer, "%s_List", pSection);
  877. m_MsgList.Init(pIniFile, Buffer);
  878. pIniFile->GetInteger(Buffer, "Font", 12, &m_nLineHeight);
  879. m_nLineHeight++;
  880. sprintf(Buffer, "%s_Scroll", pSection);
  881. m_Scroll.Init(pIniFile, Buffer);
  882. int nMinLineCount, nMaxLineCount;
  883. pIniFile->GetInteger2(pSection, "MsgLineCount", &nMinLineCount, &nMaxLineCount);
  884. InitMinMaxLineCount(nMinLineCount, nMaxLineCount);
  885. m_MsgList.SetScrollbar(&m_Scroll); //尺寸全部计算完毕后再加关系
  886. RECT rc;
  887. if (m_Style & WND_S_SIZE_WITH_ALL_CHILD)
  888. {
  889. GetAllChildLayoutRect(&rc);
  890. m_Width = rc.right - rc.left;;
  891. m_Height = rc.bottom - rc.top;
  892. }
  893. return true;
  894. }
  895. return false;
  896. }
  897. //窗口函数
  898. int KScrollMessageListBox::WndProc(unsigned int uMsg, unsigned int uParam, int nParam)
  899. {
  900. switch(uMsg)
  901. {
  902. case WND_N_SCORLLBAR_POS_CHANGED:
  903. if (uParam == (unsigned int)(KWndWindow*)&m_Scroll)
  904. {
  905. m_MsgList.SetFirstShowLine(nParam);
  906. }
  907. break;
  908. case WND_N_LIST_ITEM_SEL:
  909. if (nParam >= 0)
  910. {
  911. int nLine = m_MsgList.GetItemLineCount(nParam);
  912. int nTop = m_MsgList.GetFirstShowLine();
  913. int nBottom = nTop + m_MsgList.GetMaxShowLine();
  914. if (nLine < nTop)
  915. m_Scroll.SetScrollPos(nLine);
  916. else if (nLine >= nBottom)
  917. m_Scroll.SetScrollPos(nTop + nLine - nBottom + 1);
  918. }
  919. if (m_pParentWnd)
  920. m_pParentWnd->WndProc(uMsg, (unsigned int)(KWndWindow*)this, nParam);
  921. break;
  922. case WND_N_LIST_ITEM_D_CLICK:
  923. if (m_pParentWnd)
  924. m_pParentWnd->WndProc(uMsg, (unsigned int)(KWndWindow*)this, nParam);
  925. break;
  926. case WND_M_POPUPMENU:
  927. if (m_pParentWnd)
  928. {
  929. m_pParentWnd->WndProc(WND_M_POPUPMENU, (unsigned int)(KWndWindow*)this, nParam);
  930. }
  931. break;
  932. default:
  933. if (m_pParentWnd)
  934. return m_pParentWnd->WndProc(uMsg, uParam, nParam);
  935. return KWndWindow::WndProc(uMsg, uParam, nParam);
  936. }
  937. return 0;
  938. }
  939. void KScrollMessageListBox::InitMinMaxLineCount(int nMin, int nMax)
  940. {
  941. m_nMinLineCount = nMin;
  942. m_nMaxLineCount = nMax;
  943. if (m_nMinLineCount < 0)
  944. m_nMinLineCount = 0;
  945. if (m_nMaxLineCount <= m_nMinLineCount)
  946. m_nMaxLineCount = m_nMinLineCount + 1;
  947. }
  948. int KScrollMessageListBox::HeightToLineHeight(int nHeight)
  949. {
  950. if (m_nLineHeight <= 0)
  951. return 0;
  952. return nHeight / m_nLineHeight * m_nLineHeight;
  953. }
  954. int KScrollMessageListBox::WidthToCharWidth(int nWidth)
  955. {
  956. if (m_nLineHeight <= 0)
  957. return 0;
  958. return nWidth / m_nLineHeight * m_nLineHeight;
  959. }
  960. int KScrollMessageListBox::GetMinHeight()
  961. {
  962. return max(m_MsgList.GetMinHeight(), m_Scroll.GetMinHeight());
  963. }
  964. /////////////////////////////////////////////////////////////////////////////////
  965. /////////////////////////////////////////////////////////////////////////////////
  966. //--------------------------------------------------------------------------
  967. // 功能:从ini读取内容到KWndMessageListBox实例
  968. //  参数:pBox ->  KWndMessageListBox实例指针
  969. //   pFile -> Ini设置文件指针
  970. //   pszSection -> Ini中存储所要读取内容的段的标识
  971. //--------------------------------------------------------------------------
  972. bool MsgListBox_LoadContent(KWndMessageListBox* pBox, KIniFile* pFile, const char* pszSection)
  973. {
  974. if (pBox == NULL || pFile == NULL || pszSection == NULL)
  975. return false;
  976. pBox->Clear();
  977. char Content[516] = "", szIndex[8];
  978. int nIndex = 0;
  979. int nCapability = 0;
  980. while(true)
  981. {
  982. itoa(nIndex, szIndex, 10);
  983. if (!pFile->GetString(pszSection, szIndex, "", Content, sizeof(Content)))
  984. break;
  985. int nLen = strlen(Content);
  986. nLen = TEncodeText(Content, nLen);
  987. if (nLen <= 0)
  988. {
  989. Content[0] = ' ';
  990. Content[1] = 0;
  991. nLen = 1;
  992. }
  993. if (nIndex == nCapability)
  994. {
  995. nCapability += 16;
  996. pBox->SetCapability(nCapability);
  997. }
  998. pBox->AddOneMessage(Content, nLen);
  999. nIndex++;
  1000. };
  1001. return true;
  1002. }