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.

333 lines
6.6 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include <windows.h>
  8. #include "consolewnd.h"
  9. #pragma warning( disable : 4311 ) // warning C4311: 'reinterpret_cast' : pointer truncation from 'CConsoleWnd *const ' to 'LONG'
  10. #pragma warning( disable : 4312 ) // warning C4312: 'type cast' : conversion from 'LONG' to 'CConsoleWnd *' of greater size
  11. #define EDITCONTROL_BORDER_SIZE 5
  12. // ------------------------------------------------------------------------------------------------ //
  13. // Functions to manage the console window.
  14. // ------------------------------------------------------------------------------------------------ //
  15. class CConsoleWnd : public IConsoleWnd
  16. {
  17. public:
  18. CConsoleWnd();
  19. ~CConsoleWnd();
  20. bool Init( void *hInstance, int dialogResourceID, int editControlID, bool bVisible );
  21. void Term();
  22. virtual void Release();
  23. virtual void SetVisible( bool bVisible );
  24. virtual bool IsVisible() const;
  25. virtual void PrintToConsole( const char *pMsg );
  26. virtual void SetTitle( const char *pTitle );
  27. virtual void SetDeleteOnClose( bool bDelete );
  28. private:
  29. int WindowProc(
  30. HWND hwndDlg, // handle to dialog box
  31. UINT uMsg, // message
  32. WPARAM wParam, // first message parameter
  33. LPARAM lParam // second message parameter
  34. );
  35. static int CALLBACK StaticWindowProc(
  36. HWND hwndDlg, // handle to dialog box
  37. UINT uMsg, // message
  38. WPARAM wParam, // first message parameter
  39. LPARAM lParam // second message parameter
  40. );
  41. void RepositionEditControl();
  42. private:
  43. HWND m_hWnd;
  44. HWND m_hEditControl;
  45. bool m_bVisible;
  46. bool m_bDeleteOnClose;
  47. int m_nCurrentChars;
  48. };
  49. CConsoleWnd::CConsoleWnd()
  50. {
  51. m_hWnd = m_hEditControl = NULL;
  52. m_bVisible = false;
  53. m_bDeleteOnClose = false;
  54. m_nCurrentChars = 0;
  55. }
  56. CConsoleWnd::~CConsoleWnd()
  57. {
  58. Term();
  59. }
  60. bool CConsoleWnd::Init( void *hInstance, int dialogResourceID, int editControlID, bool bVisible )
  61. {
  62. // Create the window.
  63. m_hWnd = CreateDialog(
  64. (HINSTANCE)hInstance,
  65. MAKEINTRESOURCE( dialogResourceID ),
  66. NULL,
  67. &CConsoleWnd::StaticWindowProc );
  68. if ( !m_hWnd )
  69. return false;
  70. SetWindowLong( m_hWnd, GWL_USERDATA, reinterpret_cast< LONG >( this ) );
  71. if ( bVisible )
  72. ShowWindow( m_hWnd, SW_SHOW );
  73. // Get a handle to the edit control.
  74. m_hEditControl = GetDlgItem( m_hWnd, editControlID );
  75. if ( !m_hEditControl )
  76. return false;
  77. RepositionEditControl();
  78. m_bVisible = bVisible;
  79. return true;
  80. }
  81. void CConsoleWnd::Term()
  82. {
  83. if ( m_hWnd )
  84. {
  85. DestroyWindow( m_hWnd );
  86. m_hWnd = NULL;
  87. }
  88. }
  89. void CConsoleWnd::Release()
  90. {
  91. delete this;
  92. }
  93. void CConsoleWnd::SetVisible( bool bVisible )
  94. {
  95. ShowWindow( m_hWnd, bVisible ? SW_RESTORE : SW_HIDE );
  96. if ( bVisible )
  97. {
  98. ShowWindow( m_hWnd, SW_SHOW );
  99. SetWindowPos( m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
  100. UpdateWindow( m_hWnd );
  101. int nLen = (int)SendMessage( m_hEditControl, EM_GETLIMITTEXT, 0, 0 );
  102. SendMessage( m_hEditControl, EM_SETSEL, nLen, nLen );
  103. }
  104. else
  105. {
  106. SetWindowPos( m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW | SWP_NOOWNERZORDER );
  107. }
  108. m_bVisible = bVisible;
  109. }
  110. bool CConsoleWnd::IsVisible() const
  111. {
  112. return m_bVisible;
  113. }
  114. void CConsoleWnd::PrintToConsole( const char *pMsg )
  115. {
  116. if ( m_nCurrentChars >= 16*1024 )
  117. {
  118. // Clear the edit control otherwise it'll stop outputting anything.
  119. m_nCurrentChars = 0;
  120. int nLen = (int)SendMessage( m_hEditControl, EM_GETLIMITTEXT, 0, 0 );
  121. SendMessage( m_hEditControl, EM_SETSEL, 0, nLen );
  122. SendMessage( m_hEditControl, EM_REPLACESEL, FALSE, (LPARAM)"" );
  123. }
  124. FormatAndSendToEditControl( m_hEditControl, pMsg );
  125. m_nCurrentChars += (int)strlen( pMsg );
  126. }
  127. void CConsoleWnd::SetTitle( const char *pTitle )
  128. {
  129. SetWindowText( m_hWnd, pTitle );
  130. }
  131. int CConsoleWnd::WindowProc(
  132. HWND hwndDlg, // handle to dialog box
  133. UINT uMsg, // message
  134. WPARAM wParam, // first message parameter
  135. LPARAM lParam // second message parameter
  136. )
  137. {
  138. lParam = lParam; // avoid compiler warning
  139. if ( hwndDlg != m_hWnd )
  140. return false;
  141. switch ( uMsg )
  142. {
  143. case WM_SYSCOMMAND:
  144. {
  145. if ( wParam == SC_CLOSE )
  146. {
  147. if ( m_bDeleteOnClose )
  148. {
  149. Release();
  150. }
  151. else
  152. {
  153. SetVisible( false );
  154. return true;
  155. }
  156. }
  157. }
  158. break;
  159. case WM_SHOWWINDOW:
  160. {
  161. m_bVisible = (wParam != 0);
  162. }
  163. break;
  164. case WM_SIZE:
  165. case WM_INITDIALOG:
  166. {
  167. RepositionEditControl();
  168. }
  169. break;
  170. }
  171. return false;
  172. }
  173. int CConsoleWnd::StaticWindowProc(
  174. HWND hwndDlg, // handle to dialog box
  175. UINT uMsg, // message
  176. WPARAM wParam, // first message parameter
  177. LPARAM lParam // second message parameter
  178. )
  179. {
  180. CConsoleWnd *pDlg = (CConsoleWnd*)GetWindowLong( hwndDlg, GWL_USERDATA );
  181. if ( pDlg )
  182. return pDlg->WindowProc( hwndDlg, uMsg, wParam, lParam );
  183. else
  184. return false;
  185. }
  186. void CConsoleWnd::RepositionEditControl()
  187. {
  188. RECT rcMain;
  189. GetClientRect( m_hWnd, &rcMain );
  190. RECT rcNew;
  191. rcNew.left = rcMain.left + EDITCONTROL_BORDER_SIZE;
  192. rcNew.right = rcMain.right - EDITCONTROL_BORDER_SIZE;
  193. rcNew.top = rcMain.top + EDITCONTROL_BORDER_SIZE;
  194. rcNew.bottom = rcMain.bottom - EDITCONTROL_BORDER_SIZE;
  195. SetWindowPos(
  196. m_hEditControl,
  197. NULL,
  198. rcNew.left,
  199. rcNew.top,
  200. rcNew.right - rcNew.left,
  201. rcNew.bottom - rcNew.top,
  202. SWP_NOZORDER );
  203. }
  204. void CConsoleWnd::SetDeleteOnClose( bool bDelete )
  205. {
  206. m_bDeleteOnClose = bDelete;
  207. }
  208. // ------------------------------------------------------------------------------------ //
  209. // Module interface.
  210. // ------------------------------------------------------------------------------------ //
  211. void SendToEditControl( HWND hEditControl, const char *pText )
  212. {
  213. int nLen = (int)SendMessage( hEditControl, EM_GETLIMITTEXT, 0, 0 );
  214. SendMessage( hEditControl, EM_SETSEL, nLen, nLen );
  215. SendMessage( hEditControl, EM_REPLACESEL, FALSE, (LPARAM)pText );
  216. }
  217. void FormatAndSendToEditControl( void *hWnd, const char *pText )
  218. {
  219. HWND hEditControl = (HWND)hWnd;
  220. // Translate \n to \r\n.
  221. char outMsg[1024];
  222. const char *pIn = pText;
  223. char *pOut = outMsg;
  224. while ( *pIn )
  225. {
  226. if ( *pIn == '\n' )
  227. {
  228. *pOut = '\r';
  229. pOut++;
  230. }
  231. *pOut = *pIn;
  232. ++pIn;
  233. ++pOut;
  234. if ( pOut - outMsg >= 1020 )
  235. {
  236. *pOut = 0;
  237. SendToEditControl( hEditControl, outMsg );
  238. pOut = outMsg;
  239. }
  240. }
  241. *pOut = 0;
  242. SendToEditControl( hEditControl, outMsg );
  243. }
  244. IConsoleWnd* CreateConsoleWnd( void *hInstance, int dialogResourceID, int editControlID, bool bVisible )
  245. {
  246. CConsoleWnd *pWnd = new CConsoleWnd;
  247. if ( pWnd->Init( hInstance, dialogResourceID, editControlID, bVisible ) )
  248. {
  249. return pWnd;
  250. }
  251. else
  252. {
  253. pWnd->Release();
  254. return NULL;
  255. }
  256. }