Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

422 lines
9.5 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "stdafx.h"
  7. #include <afxtempl.h>
  8. #include "hammer.h"
  9. #include "MessageWnd.h"
  10. #include "mainfrm.h"
  11. #include "GlobalFunctions.h"
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include <tier0/memdbgon.h>
  14. IMPLEMENT_DYNCREATE(CMessageWnd, CMDIChildWnd)
  15. const int iMsgPtSize = 10;
  16. BEGIN_MESSAGE_MAP(CMessageWnd, CMDIChildWnd)
  17. //{{AFX_MSG_MAP(CMessageWnd)
  18. ON_WM_PAINT()
  19. ON_WM_HSCROLL()
  20. ON_WM_VSCROLL()
  21. ON_WM_SIZE()
  22. ON_WM_KEYDOWN()
  23. ON_WM_CLOSE()
  24. //}}AFX_MSG_MAP
  25. END_MESSAGE_MAP()
  26. //-----------------------------------------------------------------------------
  27. // Static factory function to create the message window object. The window
  28. // itself is created by CMessageWnd::CreateWindow.
  29. //-----------------------------------------------------------------------------
  30. CMessageWnd *CMessageWnd::CreateMessageWndObject()
  31. {
  32. CMessageWnd *pMsgWnd = (CMessageWnd *)RUNTIME_CLASS(CMessageWnd)->CreateObject();
  33. return pMsgWnd;
  34. }
  35. //-----------------------------------------------------------------------------
  36. //-----------------------------------------------------------------------------
  37. CMessageWnd::CMessageWnd()
  38. {
  39. // set initial elements
  40. iCharWidth = -1;
  41. iNumMsgs = 0;
  42. // load font
  43. Font.CreatePointFont(iMsgPtSize * 10, "Courier New");
  44. }
  45. //-----------------------------------------------------------------------------
  46. //-----------------------------------------------------------------------------
  47. CMessageWnd::~CMessageWnd()
  48. {
  49. }
  50. //-----------------------------------------------------------------------------
  51. //-----------------------------------------------------------------------------
  52. void CMessageWnd::CreateMessageWindow( CMDIFrameWnd *pwndParent, CRect &rect )
  53. {
  54. Create( NULL, "Messages", WS_OVERLAPPEDWINDOW | WS_CHILD, rect, pwndParent );
  55. bool bErrors = true;
  56. MWMSGSTRUCT mws;
  57. for ( int i = 0; i < iNumMsgs; i++ )
  58. {
  59. mws = MsgArray[i];
  60. if ( ( mws.type == mwError ) || ( mws.type == mwWarning ) )
  61. {
  62. bErrors = true;
  63. }
  64. }
  65. if ( bErrors )
  66. {
  67. ShowWindow( SW_SHOW );
  68. }
  69. }
  70. //-----------------------------------------------------------------------------
  71. // Emit a message to our messages array.
  72. // NOTE: During startup the window itself might not exist yet!
  73. //-----------------------------------------------------------------------------
  74. void CMessageWnd::AddMsg(MWMSGTYPE type, TCHAR* msg)
  75. {
  76. int iAddAt = iNumMsgs;
  77. // Don't allow growth after MAX_MESSAGE_WND_LINES
  78. if ( iNumMsgs == MAX_MESSAGE_WND_LINES )
  79. {
  80. MWMSGSTRUCT *p = MsgArray.GetData();
  81. memcpy(p, p+1, sizeof(*p) * ( MAX_MESSAGE_WND_LINES - 1 ));
  82. iAddAt = MAX_MESSAGE_WND_LINES - 1;
  83. }
  84. else
  85. {
  86. ++iNumMsgs;
  87. }
  88. // format message
  89. MWMSGSTRUCT mws;
  90. mws.MsgLen = strlen(msg);
  91. mws.type = type;
  92. Assert(mws.MsgLen <= (sizeof(mws.szMsg) / sizeof(TCHAR)));
  93. _tcscpy(mws.szMsg, msg);
  94. // Add the message, growing the array as necessary
  95. MsgArray.SetAtGrow(iAddAt, mws);
  96. // Don't do stuff that requires the window to exist.
  97. if ( m_hWnd == NULL )
  98. return;
  99. CalculateScrollSize();
  100. Invalidate();
  101. }
  102. //-----------------------------------------------------------------------------
  103. //-----------------------------------------------------------------------------
  104. void CMessageWnd::ShowMessageWindow()
  105. {
  106. if ( m_hWnd == NULL )
  107. return;
  108. ShowWindow( SW_SHOW );
  109. }
  110. //-----------------------------------------------------------------------------
  111. //-----------------------------------------------------------------------------
  112. void CMessageWnd::ToggleMessageWindow()
  113. {
  114. if ( m_hWnd == NULL )
  115. return;
  116. ShowWindow( IsWindowVisible() ? SW_HIDE : SW_SHOWNA );
  117. }
  118. //-----------------------------------------------------------------------------
  119. //-----------------------------------------------------------------------------
  120. void CMessageWnd::Activate()
  121. {
  122. if ( m_hWnd == NULL )
  123. return;
  124. ShowWindow( SW_SHOW );
  125. SetWindowPos( &( CWnd::wndTopMost ), 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW );
  126. BringWindowToTop();
  127. SetFocus();
  128. }
  129. //-----------------------------------------------------------------------------
  130. //-----------------------------------------------------------------------------
  131. bool CMessageWnd::IsVisible()
  132. {
  133. if ( m_hWnd == NULL )
  134. return false;
  135. return ( IsWindowVisible() == TRUE );
  136. }
  137. //-----------------------------------------------------------------------------
  138. //-----------------------------------------------------------------------------
  139. void CMessageWnd::Resize( CRect &rect )
  140. {
  141. if ( m_hWnd == NULL )
  142. return;
  143. MoveWindow( rect );
  144. }
  145. //-----------------------------------------------------------------------------
  146. //-----------------------------------------------------------------------------
  147. void CMessageWnd::CalculateScrollSize()
  148. {
  149. if ( m_hWnd == NULL )
  150. return;
  151. int iHorz;
  152. int iVert;
  153. iVert = iNumMsgs * (iMsgPtSize + 2);
  154. iHorz = 0;
  155. for(int i = 0; i < iNumMsgs; i++)
  156. {
  157. int iTmp = MsgArray[i].MsgLen * iCharWidth;
  158. if(iTmp > iHorz)
  159. iHorz = iTmp;
  160. }
  161. Invalidate();
  162. SCROLLINFO si;
  163. si.cbSize = sizeof(si);
  164. si.fMask = SIF_ALL;
  165. si.nMin = 0;
  166. si.nPos = 0;
  167. CRect clientrect;
  168. GetClientRect(clientrect);
  169. // horz
  170. si.nMax = iHorz;
  171. si.nPage = clientrect.Width();
  172. SetScrollInfo(SB_HORZ, &si);
  173. // vert
  174. si.nMax = iVert;
  175. si.nPage = clientrect.Height();
  176. SetScrollInfo(SB_VERT, &si);
  177. }
  178. //-----------------------------------------------------------------------------
  179. //-----------------------------------------------------------------------------
  180. void CMessageWnd::OnPaint()
  181. {
  182. CPaintDC dc(this); // device context for painting
  183. int nScrollMin;
  184. int nScrollMax;
  185. // select font
  186. dc.SelectObject(&Font);
  187. dc.SetBkMode(TRANSPARENT);
  188. // first paint?
  189. if(iCharWidth == -1)
  190. {
  191. dc.GetCharWidth('A', 'A', &iCharWidth);
  192. CalculateScrollSize();
  193. }
  194. GetScrollRange( SB_VERT, &nScrollMin, &nScrollMax );
  195. // paint messages
  196. MWMSGSTRUCT mws;
  197. CRect r(0, 0, 1, iMsgPtSize+2);
  198. dc.SetWindowOrg(GetScrollPos(SB_HORZ), GetScrollPos(SB_VERT));
  199. for(int i = 0; i < iNumMsgs; i++)
  200. {
  201. mws = MsgArray[i];
  202. r.right = mws.MsgLen * iCharWidth;
  203. if ( r.bottom < nScrollMin )
  204. continue;
  205. if ( r.top > nScrollMax )
  206. break;
  207. // color of msg
  208. switch(mws.type)
  209. {
  210. case mwError:
  211. dc.SetTextColor(RGB(255, 60, 60));
  212. break;
  213. case mwStatus:
  214. dc.SetTextColor(RGB(0, 0, 0));
  215. break;
  216. }
  217. // draw text
  218. dc.TextOut(r.left, r.top, mws.szMsg, mws.MsgLen);
  219. // move rect down
  220. r.OffsetRect(0, iMsgPtSize + 2);
  221. }
  222. }
  223. //-----------------------------------------------------------------------------
  224. //-----------------------------------------------------------------------------
  225. void CMessageWnd::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  226. {
  227. int iPos = int(nPos);
  228. SCROLLINFO si;
  229. GetScrollInfo(SB_HORZ, &si);
  230. int iCurPos = GetScrollPos(SB_HORZ);
  231. int iLimit = GetScrollLimit(SB_HORZ);
  232. switch(nSBCode)
  233. {
  234. case SB_LINELEFT:
  235. iPos = -int(si.nPage / 4);
  236. break;
  237. case SB_LINERIGHT:
  238. iPos = int(si.nPage / 4);
  239. break;
  240. case SB_PAGELEFT:
  241. iPos = -int(si.nPage / 2);
  242. break;
  243. case SB_PAGERIGHT:
  244. iPos = int(si.nPage / 2);
  245. break;
  246. case SB_THUMBTRACK:
  247. case SB_THUMBPOSITION:
  248. iPos -= iCurPos;
  249. break;
  250. }
  251. if(iCurPos + iPos < 0)
  252. iPos = -iCurPos;
  253. if(iCurPos + iPos > iLimit)
  254. iPos = iLimit - iCurPos;
  255. if(iPos)
  256. {
  257. SetScrollPos(SB_HORZ, iCurPos + iPos);
  258. ScrollWindow(-iPos, 0);
  259. UpdateWindow();
  260. }
  261. CMDIChildWnd::OnHScroll(nSBCode, nPos, pScrollBar);
  262. }
  263. //-----------------------------------------------------------------------------
  264. //-----------------------------------------------------------------------------
  265. void CMessageWnd::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  266. {
  267. int iPos = int(nPos);
  268. SCROLLINFO si;
  269. GetScrollInfo(SB_VERT, &si);
  270. int iCurPos = GetScrollPos(SB_VERT);
  271. int iLimit = GetScrollLimit(SB_VERT);
  272. switch(nSBCode)
  273. {
  274. case SB_LINEUP:
  275. iPos = -int(si.nPage / 4);
  276. break;
  277. case SB_LINEDOWN:
  278. iPos = int(si.nPage / 4);
  279. break;
  280. case SB_PAGEUP:
  281. iPos = -int(si.nPage / 2);
  282. break;
  283. case SB_PAGEDOWN:
  284. iPos = int(si.nPage / 2);
  285. break;
  286. case SB_THUMBTRACK:
  287. case SB_THUMBPOSITION:
  288. iPos -= iCurPos;
  289. break;
  290. }
  291. if(iCurPos + iPos < 0)
  292. iPos = -iCurPos;
  293. if(iCurPos + iPos > iLimit)
  294. iPos = iLimit - iCurPos;
  295. if(iPos)
  296. {
  297. SetScrollPos(SB_VERT, iCurPos + iPos);
  298. ScrollWindow(0, -iPos);
  299. UpdateWindow();
  300. }
  301. CMDIChildWnd::OnVScroll(nSBCode, nPos, pScrollBar);
  302. }
  303. //-----------------------------------------------------------------------------
  304. //-----------------------------------------------------------------------------
  305. void CMessageWnd::OnSize(UINT nType, int cx, int cy)
  306. {
  307. CMDIChildWnd::OnSize(nType, cx, cy);
  308. CalculateScrollSize();
  309. }
  310. //-----------------------------------------------------------------------------
  311. //-----------------------------------------------------------------------------
  312. void CMessageWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  313. {
  314. // up/down
  315. switch(nChar)
  316. {
  317. case VK_UP:
  318. OnVScroll(SB_LINEUP, 0, NULL);
  319. break;
  320. case VK_DOWN:
  321. OnVScroll(SB_LINEDOWN, 0, NULL);
  322. break;
  323. case VK_PRIOR:
  324. OnVScroll(SB_PAGEUP, 0, NULL);
  325. break;
  326. case VK_NEXT:
  327. OnVScroll(SB_PAGEDOWN, 0, NULL);
  328. break;
  329. case VK_HOME:
  330. OnVScroll(SB_THUMBPOSITION, 0, NULL);
  331. break;
  332. case VK_END:
  333. OnVScroll(SB_THUMBPOSITION, GetScrollLimit(SB_VERT), NULL);
  334. break;
  335. }
  336. CMDIChildWnd::OnKeyDown(nChar, nRepCnt, nFlags);
  337. }
  338. //-----------------------------------------------------------------------------
  339. //-----------------------------------------------------------------------------
  340. void CMessageWnd::OnClose()
  341. {
  342. // just hide the window
  343. ShowWindow(SW_HIDE);
  344. }