Source code of Windows XP (NT5)
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.

3286 lines
78 KiB

  1. // NmChatCtl.cpp : Implementation of CNmChatCtl
  2. #include "precomp.h"
  3. #include "NmCtl1.h"
  4. #include "NmChatCtl.h"
  5. #include "ComboBoxEx.h"
  6. #include "Message.h"
  7. #include "OprahCom.h"
  8. #include <version.h>
  9. #include <nmhelp.h>
  10. #include <help_ids.h>
  11. extern CChatObj *g_pChatObj;
  12. extern DWORD g_dwWorkThreadID;
  13. // Class name
  14. TCHAR szMainClassName[] = "ChatMainWindowClass";
  15. static const TCHAR s_cszHtmlHelpFile[] = TEXT("nmchat.chm");
  16. static const DWORD _mpIdHelpChatOptions[] = {
  17. // Information display group
  18. IDR_MESSAGE_GROUP, IDH_CHAT_FORMAT_HEADER,
  19. IDC_INCLUDE_NAME, IDH_CHAT_NAME,
  20. IDC_INCLUDE_DATE, IDH_CHAT_DATE,
  21. IDC_INCLUDE_TIME, IDH_CHAT_TIME,
  22. // Message Format group
  23. IDC_HEADER_GROUP, IDH_CHAT_FORMAT_MESSAGE,
  24. IDR_SINGLE_LINE, IDH_CHAT_FORMAT_MESSAGE,
  25. IDR_SAME_LINE, IDH_CHAT_FORMAT_MESSAGE,
  26. IDR_NEW_LINE, IDH_CHAT_FORMAT_MESSAGE,
  27. IDC_FORMATSINGLE, IDH_CHAT_FORMAT_MESSAGE,
  28. IDC_FORMATWRAP, IDH_CHAT_FORMAT_MESSAGE,
  29. IDC_FORMATWRAPNEW, IDH_CHAT_FORMAT_MESSAGE,
  30. // Font buttons and edit controls
  31. IDC_FONTS_GROUP, IDH_CHAT_FONTS_LABEL,
  32. IDC_FONT_MSGIN, IDH_CHAT_RECEIVE_MSG,
  33. IDC_EDIT_MSGIN, IDH_CHAT_FONT,
  34. IDC_FONT_PRIVATEIN, IDH_CHAT_RECEIVE_PRIV,
  35. IDC_EDIT_PRIVATEIN, IDH_CHAT_FONT,
  36. IDC_FONT_MSGOUT, IDH_CHAT_SENT_MSG,
  37. IDC_EDIT_MSGOUT, IDH_CHAT_FONT,
  38. IDC_FONT_PRIVATEOUT, IDH_CHAT_SENT_PRIV,
  39. IDC_EDIT_PRIVATEOUT, IDH_CHAT_FONT,
  40. // terminator
  41. 0, 0
  42. };
  43. // Option entry names
  44. #define OPT_MAIN_INFORMATION_DISPLAY_NAME "Information Display Name"
  45. #define OPT_MAIN_INFORMATION_DISPLAY_TIME "Information Display Time"
  46. #define OPT_MAIN_INFORMATION_DISPLAY_DATE "Information Display Date"
  47. #define OPT_MAIN_MESSAGE_FORMAT "Message format"
  48. const LPTSTR OPT_FONT_FORMAT[] = {"Received Message", "Received Private Messages",
  49. "Send Messages", "Send Private Messages", "System Format"};
  50. const LPTSTR OPT_FONT_COLOR[] = {"Received Message Color", "Received Private Messages Color",
  51. "Send Messages Color", "Send Private Messages Color", "System Format Color"};
  52. extern CNmChatCtl *g_pChatWindow;
  53. CNmChatCtl *CNmChatCtl::ms_pThis = NULL;
  54. WORD CChatOptionsDlg::IDD = IDD_CHAT_OPTIONS;
  55. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  56. // CNmChatCtl Construction and initialization
  57. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  58. CNmChatCtl::CNmChatCtl( void )
  59. : m_hWndMsg( NULL ),
  60. m_himlIconSmall( NULL ),
  61. m_cOtherMembers( 0 ),
  62. m_hMenuShared(NULL),
  63. m_cchBufferSize( 0 ),
  64. m_hInstRichEd32( NULL ),
  65. m_bUseName( -1 ),
  66. m_bTimeStamp( 0 ),
  67. m_bUseDate( 0 ),
  68. m_style( MSGSTYLE_2_LINE_WRAP ),
  69. m_lpszOwnName( NULL ),
  70. m_iNameLen( 0 ),
  71. m_iStaticLen( 0 ),
  72. m_iDLGUX( 0 ),
  73. m_iDLGUY( 0 ),
  74. m_iStaticY( 0 ),
  75. m_iExtra( 0 ),
  76. m_szTo( NULL ),
  77. m_szPrivate( NULL ),
  78. m_bWeAreActiveApp(false),
  79. m_dwChatFlags( CHAT_FLAG_NONE ),
  80. m_hWndPrint( NULL ),
  81. m_lpszSaveFile( NULL ),
  82. m_bStatusBarVisible( TRUE ),
  83. m_wFileOffset( 0 ),
  84. m_lpszRichEdEOL( NULL ),
  85. m_lpszRichEd( NULL ),
  86. m_pChatOptions( NULL ),
  87. m_cMessages( 0 )
  88. {
  89. DBGENTRY(CNmChatCtl::CNmChatCtl);
  90. g_pChatWindow = this;
  91. // Ensure the common controls are loaded
  92. INITCOMMONCONTROLSEX icc;
  93. icc.dwSize = sizeof(icc);
  94. icc.dwICC = ICC_WIN95_CLASSES | ICC_COOL_CLASSES | ICC_USEREX_CLASSES;
  95. ::InitCommonControlsEx(&icc);
  96. _LoadIconImages();
  97. _InitFontsAndColors();
  98. //
  99. // CREATE THE MAIN FRAME WINDOW
  100. //
  101. //
  102. // Get the class info for it, and change the name.
  103. //
  104. WNDCLASSEX wc;
  105. ZeroMemory(&wc, sizeof(wc));
  106. wc.cbSize = sizeof(wc);
  107. wc.style = CS_DBLCLKS; // CS_HREDRAW | CS_VREDRAW?
  108. wc.lpfnWndProc = ChatMainWindowProc;
  109. wc.hInstance = g_hInstance;
  110. wc.hIcon = ::LoadIcon(g_hInstance, MAKEINTRESOURCE(CHAT_ICON));
  111. wc.hCursor = ::LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
  112. wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
  113. wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_CHAT_WITHFILE);
  114. wc.lpszClassName = szMainClassName;
  115. if (!::RegisterClassEx(&wc))
  116. {
  117. ERROR_OUT(("Can't register private frame window class"));
  118. }
  119. TCHAR szCaption[MAX_PATH * 2];
  120. ::LoadString(g_hInstance, IDS_CHAT_NOT_IN_CALL_WINDOW_CAPTION, szCaption, sizeof(szCaption) );
  121. m_hWnd = ::CreateWindow(
  122. szMainClassName,
  123. szCaption,
  124. WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
  125. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  126. NULL, // no parent window
  127. NULL, // use class' menu
  128. g_hInstance,
  129. (LPVOID) this); // this window is for this object
  130. m_hMenuShared = ::GetMenu(m_hWnd);
  131. ASSERT(m_hWnd);
  132. DBGEXIT(CNmChatCtl::CNmChatCtl);
  133. }
  134. CNmChatCtl::~CNmChatCtl( void )
  135. {
  136. DBGENTRY(CNmChatCtl::~CNmChatCtl);
  137. delete [] m_lpszOwnName;
  138. delete [] m_szTo;
  139. delete [] m_szPrivate;
  140. delete [] m_lpszSaveFile;
  141. delete [] m_lpszRichEdEOL;
  142. delete [] m_lpszRichEd;
  143. if( NULL != m_hInstRichEd32 )
  144. FreeLibrary( m_hInstRichEd32 );
  145. CChatMessage::DeleteAll();
  146. m_pButton->Release();
  147. _DeleteFonts();
  148. _FreeIconImages();
  149. delete m_pChatOptions;
  150. DBGEXIT(CNmChatCtl::~CNmChatCtl);
  151. }
  152. //
  153. // FilterMessage()
  154. //
  155. // This does tooltip message filtering, then translates accelerators.
  156. //
  157. BOOL CNmChatCtl::FilterMessage(MSG* pMsg)
  158. {
  159. return ( (m_hAccelTable != NULL)
  160. && ::TranslateAccelerator(m_hWnd, m_hAccelTable, pMsg));
  161. }
  162. //
  163. // ChatMainWindowProc()
  164. // Frame window message handler
  165. //
  166. LRESULT CNmChatCtl::ChatMainWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  167. {
  168. LRESULT lResult = 0;
  169. CNmChatCtl * pMain;
  170. LPWINDOWPOS pos;
  171. pMain = (CNmChatCtl *)::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  172. switch (message)
  173. {
  174. case WM_NCCREATE:
  175. pMain = (CNmChatCtl *)((LPCREATESTRUCT)lParam)->lpCreateParams;
  176. ASSERT(pMain);
  177. pMain->m_hWnd = hwnd;
  178. ::SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pMain);
  179. pMain->OnCreate(wParam,lParam);
  180. goto DefWndProc;
  181. break;
  182. case WM_CREATE:
  183. ::SetFocus(pMain->m_hWndEdit);
  184. break;
  185. case WM_NCDESTROY:
  186. pMain->m_hWnd = NULL;
  187. break;
  188. case WM_MENUSELECT:
  189. pMain->OnMenuSelect((DWORD)wParam, (DWORD)lParam);
  190. break;
  191. case WM_INITMENUPOPUP:
  192. pMain->OnInitMenuPopup((DWORD)wParam, (DWORD)lParam);
  193. break;
  194. case WM_ENDSESSION:
  195. case WM_CLOSE:
  196. pMain->cmdFileExit(wParam);
  197. break;
  198. case WM_COMMAND:
  199. pMain->OnCommand((DWORD)wParam, (DWORD)lParam);
  200. break;
  201. case WM_CONTEXTMENU:
  202. pMain->OnContextMenu((short)LOWORD(lParam), (short)HIWORD(lParam));
  203. break;
  204. case WM_SIZE:
  205. pMain->_Resize(0, 0, (short)LOWORD(lParam), (short)HIWORD(lParam));
  206. break;
  207. case WM_GETMINMAXINFO:
  208. if (pMain)
  209. {
  210. pMain->OnGetMinMaxInfo((LPMINMAXINFO)lParam);
  211. }
  212. break;
  213. case WM_USER_BRING_TO_FRONT_WINDOW:
  214. pMain->BringToFront();
  215. break;
  216. case WM_ACTIVATE:
  217. if (WA_INACTIVE != LOWORD(wParam) && IsWindowVisible(pMain->m_hWndEdit))
  218. {
  219. ::SetFocus(pMain->m_hWndEdit);
  220. }
  221. break;
  222. case WM_NOTIFY:
  223. if(EN_LINK == ((LPNMHDR)lParam)->code)
  224. {
  225. pMain->OnNotifyEnLink((ENLINK*)lParam);
  226. }
  227. break;
  228. default:
  229. DefWndProc:
  230. lResult = ::DefWindowProc(hwnd, message, wParam, lParam);
  231. break;
  232. }
  233. return(lResult);
  234. }
  235. void CNmChatCtl::BringToFront(void)
  236. {
  237. if (NULL != m_hWnd)
  238. {
  239. int nCmdShow = SW_SHOW;
  240. WINDOWPLACEMENT wp;
  241. ::ZeroMemory(&wp, sizeof(wp));
  242. wp.length = sizeof(wp);
  243. if (::GetWindowPlacement(m_hWnd, &wp))
  244. {
  245. if (SW_MINIMIZE == wp.showCmd || SW_SHOWMINIMIZED == wp.showCmd)
  246. {
  247. // The window is minimized - restore it:
  248. nCmdShow = SW_RESTORE;
  249. }
  250. }
  251. // show the window now
  252. ::ShowWindow(m_hWnd, nCmdShow);
  253. // bring it to the foreground
  254. ::SetForegroundWindow(m_hWnd);
  255. //
  256. // Set the focus on the edit box
  257. //
  258. ::SetFocus(m_hWndEdit);
  259. }
  260. }
  261. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  262. // CNmChatCtl Window message and command handlers
  263. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  264. LRESULT CNmChatCtl::OnCreate(WPARAM wParam, LPARAM lParam)
  265. {
  266. DBGENTRY(CNmChatCtl::OnCreate);
  267. RECT rc;
  268. SetRect( &rc, 0, 0, 0, 0 );
  269. if( NULL == ( m_hInstRichEd32 = ::LoadLibrary( "RICHED20.DLL" ) ) )
  270. {
  271. if( NULL == ( m_hInstRichEd32 = ::LoadLibrary( "RICHED32.DLL" ) ) )
  272. {
  273. return 0;
  274. }
  275. else
  276. {
  277. LPTSTR szValue = TEXT("RichEdit");
  278. LPTSTR szValueEOL = TEXT("\r\n");
  279. DBG_SAVE_FILE_LINE
  280. m_lpszRichEd = new TCHAR[ lstrlen( szValue ) + 1 ];
  281. lstrcpy( m_lpszRichEd, szValue );
  282. m_lpszRichEdEOL = new TCHAR[ lstrlen( szValueEOL ) + 1 ];
  283. lstrcpy( m_lpszRichEdEOL, szValueEOL );
  284. }
  285. }
  286. else
  287. {
  288. LPTSTR szValue = RICHEDIT_CLASS;
  289. LPTSTR szValueEOL = TEXT(" \r");
  290. DBG_SAVE_FILE_LINE
  291. m_lpszRichEd = new TCHAR[ lstrlen( szValue ) + 1 ];
  292. lstrcpy( m_lpszRichEd, szValue );
  293. DBG_SAVE_FILE_LINE
  294. m_lpszRichEdEOL = new TCHAR[ lstrlen( szValueEOL ) + 1 ];
  295. lstrcpy( m_lpszRichEdEOL, szValueEOL );
  296. }
  297. ////////// Edit control
  298. m_hWndEdit = ::CreateWindowEx(WS_EX_CLIENTEDGE,
  299. _T("EDIT"),
  300. NULL,
  301. WS_CHILD | WS_BORDER | WS_VISIBLE |
  302. WS_TABSTOP | ES_MULTILINE | ES_AUTOVSCROLL,
  303. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
  304. m_hWnd, NULL, g_hInstance, NULL);
  305. ::SendMessage( m_hWndEdit, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT ), TRUE);
  306. ::SendMessage( m_hWndEdit, EM_LIMITTEXT, CCHMAX_CHAT_MSG - 1, 0 );
  307. ::SendMessage( m_hWndEdit, EM_EXLIMITTEXT, 0, CCHMAX_CHAT_MSG - 1 );
  308. //// Get info from edit control
  309. TEXTMETRIC textmex;
  310. ZeroMemory( &textmex, sizeof( textmex ) );
  311. HDC hdc = GetDC(m_hWndEdit);
  312. GetTextMetrics( hdc, &textmex );
  313. ReleaseDC(m_hWndEdit, hdc );
  314. m_iDLGUY = PIX_FROM_DLGU_Y( 1, textmex.tmHeight );
  315. m_iDLGUX = PIX_FROM_DLGU_X( 1, textmex.tmAveCharWidth);
  316. ////////// Send Button
  317. DBG_SAVE_FILE_LINE
  318. m_pButton = new CBitmapButton();
  319. if(m_pButton)
  320. {
  321. BOOL fRet = m_pButton->Create(m_hWnd,
  322. IDI_SENDBUTTON,
  323. g_hInstance,
  324. IDB_SENDCHAT,
  325. TRUE,
  326. CBitmapButton::Disabled,
  327. 1,
  328. NULL);
  329. m_hWndSend = m_pButton->GetWindow();
  330. if(fRet == FALSE)
  331. {
  332. m_pButton->Release();
  333. return fRet;
  334. }
  335. m_pButton->SetTooltip((LPSTR)IDS_TOOLTIP_SEND_MESSAGE);
  336. }
  337. else
  338. {
  339. return FALSE;
  340. }
  341. ////////// Member List
  342. m_hWndMemberList = ::CreateWindowEx(0,
  343. _T(WC_COMBOBOXEX),
  344. NULL,
  345. WS_VISIBLE | WS_CHILD | CBS_DROPDOWNLIST | WS_TABSTOP | WS_VSCROLL,
  346. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
  347. m_hWnd, NULL, g_hInstance, NULL);
  348. ASSERT( m_himlIconSmall );
  349. ::SendMessage(m_hWndMemberList, WM_SETFONT, (WPARAM)GetStockObject( DEFAULT_GUI_FONT ), TRUE);
  350. ComboBoxEx_SetImageList( m_hWndMemberList, m_himlIconSmall );
  351. int yFrameBorder = GetSystemMetrics( SM_CYFIXEDFRAME );
  352. int ySpace = GetSystemMetrics( SM_CYBORDER );
  353. int iHeight = ComboBoxEx_GetItemHeight( m_hWndMemberList, 0 );
  354. ComboBoxEx_SetHeight( m_hWndMemberList, ((iHeight + ySpace) * MSGLIST_VISMEMBERS) + yFrameBorder);
  355. ////////// Status bar
  356. RECT clientRect;
  357. ::GetClientRect(m_hWnd, &clientRect);
  358. m_hwndSB = ::CreateWindowEx(0, STATUSCLASSNAME, NULL,
  359. WS_CHILD | WS_VISIBLE | CCS_NOPARENTALIGN | CCS_NOMOVEY |
  360. CCS_NORESIZE | SBARS_SIZEGRIP,
  361. clientRect.left, clientRect.bottom - STATUSBAR_HEIGHT,
  362. (clientRect.right - clientRect.left), STATUSBAR_HEIGHT,
  363. m_hWnd, 0, g_hInstance, NULL);
  364. if (!m_hwndSB)
  365. {
  366. ERROR_OUT(("Failed to create status bar window"));
  367. return(FALSE);
  368. }
  369. ////////// Static
  370. TCHAR szBuff[ MAX_PATH ];
  371. NmCtlLoadString( IDS_CHAT_MESSAGE, szBuff, CCHMAX(szBuff));
  372. m_hWndStaticMessage = ::CreateWindowEx(0,
  373. _T("STATIC"),
  374. szBuff,
  375. WS_VISIBLE | WS_CHILD | SS_LEFT,
  376. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
  377. m_hWnd, NULL, g_hInstance, NULL);
  378. ::SendMessage(m_hWndStaticMessage, WM_SETFONT, (WPARAM)GetStockObject( DEFAULT_GUI_FONT ), TRUE);
  379. ////////// Static
  380. NmCtlLoadString( IDS_CHAT_SENDTO, szBuff, CCHMAX(szBuff));
  381. m_hWndStaticSendTo = ::CreateWindowEx(0,
  382. _T("STATIC"),
  383. szBuff,
  384. WS_VISIBLE | WS_CHILD | SS_LEFT,
  385. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
  386. m_hWnd, NULL, g_hInstance, NULL);
  387. ::SendMessage(m_hWndStaticSendTo, WM_SETFONT, (WPARAM)GetStockObject( DEFAULT_GUI_FONT ), TRUE);
  388. ////// Get info for static controls
  389. hdc = ::GetDC(m_hWndStaticMessage);
  390. GetTextMetrics( hdc, &textmex );
  391. TCHAR szBuffer[ MAX_PATH ];
  392. GetWindowText(m_hWndStaticMessage, szBuffer, CCHMAX( szBuffer ) );
  393. RECT rect1;
  394. ZeroMemory( &rect1, sizeof( rect1 ) );
  395. DrawText( hdc, szBuffer, lstrlen( szBuffer ), &rect1, DT_CALCRECT );
  396. GetWindowText(m_hWndStaticSendTo, szBuffer, CCHMAX( szBuffer ) );
  397. RECT rect2;
  398. ZeroMemory( &rect2, sizeof( rect2 ) );
  399. DrawText( hdc, szBuffer, lstrlen( szBuffer ), &rect1, DT_CALCRECT );
  400. ReleaseDC(m_hWndStaticMessage, hdc );
  401. m_iStaticLen = max( rect1.right, rect2.right );
  402. m_iStaticY = max( rect1.bottom, rect2.bottom );
  403. _UpdateContainerCaption();
  404. put_MsgStyle( m_style );
  405. _LoadStrings();
  406. HICON hIconSmall = (HICON)LoadImage(
  407. g_hInstance, // handle of the instance containing the image
  408. MAKEINTRESOURCE( CHAT_ICON ), // name or identifier of image
  409. IMAGE_ICON, // type of image
  410. ICON_SMALL_SIZE, // desired width
  411. ICON_SMALL_SIZE, // desired height
  412. LR_DEFAULTCOLOR // load flags
  413. );
  414. HICON hIconLarge = (HICON)LoadImage(
  415. g_hInstance, // handle of the instance containing the image
  416. MAKEINTRESOURCE( CHAT_ICON ), // name or identifier of image
  417. IMAGE_ICON, // type of image
  418. ICON_BIG_SIZE, // desired width
  419. ICON_BIG_SIZE, // desired height
  420. LR_DEFAULTCOLOR // load flags
  421. );
  422. DBGEXIT_ULONG(CNmChatCtl::OnCreate, 0);
  423. // Load the main accelerator table
  424. m_hAccelTable = ::LoadAccelerators(g_hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR));
  425. RECT rcUI;
  426. _GetWindowRectOption(&rcUI);
  427. ::MoveWindow(m_hWnd, rcUI.left, rcUI.top, rcUI.right - rcUI.left, rcUI.bottom - rcUI.top, TRUE);
  428. return TRUE;
  429. }
  430. void CNmChatCtl::_LoadStrings()
  431. {
  432. TCHAR buffer[ MAX_PATH ];
  433. NmCtlLoadString(IDS_PRIVATE, buffer, CCHMAX(buffer));
  434. DBG_SAVE_FILE_LINE
  435. m_szPrivate = new TCHAR[ lstrlen( buffer ) + 1 ];
  436. ASSERT( m_szPrivate );
  437. lstrcpy( m_szPrivate, buffer );
  438. NmCtlLoadString(IDS_TO, buffer, CCHMAX(buffer));
  439. DBG_SAVE_FILE_LINE
  440. m_szTo = new TCHAR[ lstrlen( buffer ) + 1 ];
  441. ASSERT( m_szTo );
  442. lstrcpy( m_szTo, buffer );
  443. m_iExtra = lstrlen( m_szTo ) + lstrlen( m_szPrivate ) + 1;
  444. }
  445. void CNmChatCtl::_InitFontsAndColors()
  446. {
  447. if (_LoadChatOptions())
  448. { // Load options succeed
  449. return;
  450. }
  451. // Load Fonts
  452. for( int i = 0; i < CChatOptionsDlg::FONT_COUNT; i++ )
  453. {
  454. GetObject( GetStockObject( DEFAULT_GUI_FONT ), sizeof( m_hMsgLogFonts[i] ), &m_hMsgLogFonts[i] );
  455. m_hMsgFonts[ i ] = CreateFontIndirect( &m_hMsgLogFonts[i] );
  456. }
  457. m_hMsgColors[ CChatOptionsDlg::FONT_MSGOUT ] = RGB( 0, 0, 0 );
  458. m_hMsgColors[ CChatOptionsDlg::FONT_MSGIN ] = RGB( 0, 0, 0 );
  459. m_hMsgColors[ CChatOptionsDlg::FONT_PRIVATEOUT ] = RGB( 100, 100, 100 );
  460. m_hMsgColors[ CChatOptionsDlg::FONT_PRIVATEIN ] = RGB( 100, 100, 100 );
  461. m_hMsgColors[ CChatOptionsDlg::FONT_MSGSYSTEM ] = RGB( 255, 0, 0 );
  462. }
  463. void CNmChatCtl::_DeleteFonts()
  464. {
  465. for( int i = 0; i < CChatOptionsDlg::FONT_COUNT; i++ )
  466. {
  467. DeleteObject( m_hMsgFonts[i] );
  468. }
  469. }
  470. LRESULT CNmChatCtl::OnInitMenuPopup(WPARAM wParam, LPARAM lParam)
  471. {
  472. DBGENTRY(CNmChatCtl::OnInitMenuPopup);
  473. if( FALSE == (BOOL)HIWORD(lParam ) )
  474. {
  475. switch( LOWORD( lParam ) )
  476. {
  477. case MENUPOS_FILE:
  478. {
  479. if( CChatMessage::get_count() )
  480. {
  481. EnableMenuItem( m_hMenuShared, ID_FILE_SAVE,
  482. ( m_lpszSaveFile && *m_lpszSaveFile ) ? MF_ENABLED : MF_GRAYED );
  483. EnableMenuItem( m_hMenuShared, ID_FILE_SAVEAS, MF_ENABLED );
  484. EnableMenuItem( m_hMenuShared, ID_FILE_PRINT,
  485. !_IsPrinting() ? MF_ENABLED : MF_GRAYED );
  486. }
  487. else
  488. {
  489. EnableMenuItem( m_hMenuShared, ID_FILE_SAVE, MF_GRAYED );
  490. EnableMenuItem( m_hMenuShared, ID_FILE_SAVEAS, MF_GRAYED );
  491. EnableMenuItem( m_hMenuShared, ID_FILE_PRINT, MF_GRAYED );
  492. }
  493. return 0;
  494. }
  495. case MENUPOS_EDIT:
  496. {
  497. EnableMenuItem( m_hMenuShared, ID_EDIT_CLEARALL,
  498. CChatMessage::get_count() && !_IsPrinting() ? MF_ENABLED : MF_GRAYED );
  499. int iEnable = 0;
  500. HWND hwnd = ::GetFocus();
  501. if(hwnd == m_hWndEdit)
  502. {
  503. iEnable = (int)::SendMessage( hwnd, EM_GETSEL, 0, 0 );
  504. iEnable = (HIWORD(iEnable) == LOWORD(iEnable)) ? MF_GRAYED : MF_ENABLED;
  505. }
  506. else if(hwnd == m_hWndMsg)
  507. {
  508. CHARRANGE range;
  509. ::SendMessage( hwnd, EM_EXGETSEL, 0, (LPARAM) &range );
  510. iEnable = (range.cpMin == range.cpMax) ? MF_GRAYED : MF_ENABLED;
  511. }
  512. EnableMenuItem( m_hMenuShared, ID_EDIT_CUT,hwnd == m_hWndEdit ? iEnable : MF_GRAYED);
  513. EnableMenuItem( m_hMenuShared, ID_EDIT_PASTE,
  514. (IsClipboardFormatAvailable( CF_TEXT ) && (hwnd == m_hWndEdit)) ? MF_ENABLED : MF_GRAYED );
  515. EnableMenuItem( m_hMenuShared, ID_EDIT_COPY, iEnable );
  516. return 0;
  517. }
  518. case MENUPOS_VIEW:
  519. {
  520. _SetMenuItemCheck( ID_VIEW_STATUSBAR, _IsStatusBarVisibleFlagSet() );
  521. _SetMenuItemCheck( ID_VIEW_EDITWINDOW, _IsEditWindowVisibleFlagSet() );
  522. EnableMenuItem( m_hMenuShared, ID_VIEW_OPTIONS, _IsPrinting() ? MF_GRAYED : MF_ENABLED );
  523. return 0;
  524. break;
  525. }
  526. default:
  527. return 0;
  528. }
  529. }
  530. return 0;
  531. }
  532. LRESULT CNmChatCtl::OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam)
  533. {
  534. DBGENTRY(CNmChatCtl::OnMenuSelect);
  535. UINT fuFlags = HIWORD( wParam );
  536. // If fuFlags == 0xffff and NULL == lParam, the menu is closed
  537. if( !( ( 0xFFFF == fuFlags ) && ( NULL == lParam ) ) )
  538. {
  539. UINT uStringID = 0;
  540. if( ( HIWORD( wParam ) & MF_HILITE ) )
  541. {
  542. if(( HIWORD( wParam ) & MF_SYSMENU))
  543. {
  544. uStringID = LOWORD( wParam );
  545. if(!uStringID)
  546. {
  547. uStringID = IDS_SYSTEM_HELP;
  548. }
  549. }
  550. else
  551. {
  552. switch( LOWORD( wParam ) )
  553. {
  554. case 0: // FILE top-level item
  555. uStringID = IDS_HELPTEXT_CHAT_FILE;
  556. break;
  557. case 1: // EDIT top-level item
  558. uStringID = IDS_HELPTEXT_CHAT_EDIT;
  559. break;
  560. case 2: // VIEW top-level item
  561. uStringID = IDS_HELPTEXT_CHAT_VIEW;
  562. break;
  563. case 3: // OPTIONS top-level item
  564. uStringID = IDS_HELPTEXT_CHAT_HELP;
  565. break;
  566. case ID_SEND_MESSAGE:
  567. uStringID = IDS_HELPTEXT_CHAT_FILE_SEND_MESSAGE;
  568. break;
  569. case ID_FILE_SAVE:
  570. uStringID = IDS_HELPTEXT_CHAT_FILE_SAVE;
  571. break;
  572. case ID_FILE_SAVEAS:
  573. uStringID = IDS_HELPTEXT_CHAT_FILE_SAVEAS;
  574. break;
  575. case ID_FILE_PRINT:
  576. uStringID = IDS_HELPTEXT_CHAT_FILE_PRINT;
  577. break;
  578. case ID_FILE_EXIT:
  579. uStringID = IDS_HELPTEXT_CHAT_FILE_EXIT;
  580. break;
  581. case ID_VIEW_EDITWINDOW:
  582. uStringID = IDS_HELPTEXT_CHAT_VIEW_EDITWINDOW;
  583. break;
  584. case ID_VIEW_STATUSBAR:
  585. uStringID = IDS_VIEW_STATUSBAR_HELP;
  586. break;
  587. case ID_VIEW_OPTIONS:
  588. uStringID = IDS_HELPTEXT_CHAT_VIEW_OPTIONS;
  589. break;
  590. case ID_EDIT_CUT:
  591. uStringID = IDS_HELPTEXT_EDIT_CUT ;
  592. break;
  593. case ID_EDIT_COPY:
  594. uStringID = IDS_HELPTEXT_EDIT_COPY;
  595. break;
  596. case ID_EDIT_PASTE:
  597. uStringID = IDS_HELPTEXT_EDIT_PASTE;
  598. break;
  599. case ID_EDIT_CLEARALL:
  600. uStringID = IDS_HELPTEXT_EDIT_CLEARALL;
  601. break;
  602. case ID_HELP_ABOUTCHAT:
  603. uStringID = IDS_HELPTEXT_HELP_ABOUTCHAT;
  604. break;
  605. case ID_HELP_HELPTOPICS:
  606. uStringID = IDS_HELPTEXT_HELP_HELPTOPICS;
  607. break;
  608. }
  609. }
  610. _SetContainerStatusText(uStringID);
  611. }
  612. }
  613. DBGEXIT(CNmChatCtl::OnMenuSelect);
  614. return 0;
  615. }
  616. void CNmChatCtl::OnSendClicked(void)
  617. {
  618. DBGENTRY(CNmChatCtl::OnSendClicked);
  619. _SendChatText();
  620. ::SetFocus( m_hWndEdit );
  621. DBGEXIT(CNmChatCtl::OnCreate);
  622. }
  623. LRESULT CNmChatCtl::OnNotifyEnLink(ENLINK *pEnLink)
  624. {
  625. DBGENTRY(CNmChatCtl::OnMsgWndNotify);
  626. switch( pEnLink->msg )
  627. {
  628. case WM_LBUTTONUP:
  629. case WM_LBUTTONDBLCLK:
  630. {
  631. return 1;
  632. break;
  633. }
  634. case WM_LBUTTONDOWN:
  635. {
  636. TEXTRANGE Range;
  637. ZeroMemory( &Range, sizeof( TEXTRANGE ) );
  638. DBG_SAVE_FILE_LINE
  639. Range.lpstrText = new TCHAR[ pEnLink->chrg.cpMax - pEnLink->chrg.cpMin + 1];
  640. ASSERT( Range.lpstrText );
  641. Range.chrg = pEnLink->chrg;
  642. ::SendMessage( m_hWndMsg, EM_GETTEXTRANGE, 0L, (LPARAM)&Range );
  643. ShellExecute( m_hWndMsg, NULL, Range.lpstrText, NULL, NULL, SW_SHOWNORMAL );
  644. delete [] Range.lpstrText;
  645. return 1;
  646. break;
  647. }
  648. default:
  649. {
  650. break;
  651. }
  652. }
  653. DBGEXIT(CNmChatCtl::OnMsgWndNotify);
  654. return 0;
  655. }
  656. //////////////////////////////////////////////////////////////////////////
  657. void CNmChatCtl::cmdFileSave(void)
  658. {
  659. DBGENTRY(CNmChatCtl::cmdFileSave);
  660. if( ( NULL == m_lpszSaveFile ) || ( _T('\0') == *m_lpszSaveFile ) )
  661. {
  662. _SaveAs();
  663. }
  664. else
  665. {
  666. _Save();
  667. }
  668. DBGEXIT(CNmChatCtl::cmdFileSave);
  669. }
  670. void CNmChatCtl::cmdFileSaveAs(void)
  671. {
  672. DBGENTRY(CNmChatCtl::cmdFileSaveAs);
  673. _SaveAs();
  674. DBGEXIT(CNmChatCtl::cmdFileSaveAs);
  675. }
  676. void CNmChatCtl::cmdFilePrint(void)
  677. {
  678. DBGENTRY(CNmChatCtl::cmdFilePrint);
  679. m_dwChatFlags |= CHAT_PRINT_FLAG_PRINTING;
  680. _Print();
  681. m_dwChatFlags &= ~CHAT_PRINT_FLAG_PRINTING;
  682. DBGEXIT(CNmChatCtl::cmdFilePrint);
  683. }
  684. void CNmChatCtl::cmdFileExit(WPARAM wParam)
  685. {
  686. DBGENTRY(CNmChatCtl::cmdFileExit);
  687. int iOnSave = IDOK;
  688. if(wParam == 0)
  689. {
  690. // Check whether there are changes to be saved
  691. iOnSave = QueryEndSession();
  692. }
  693. // If the exit was not cancelled, close the application
  694. if (iOnSave != IDCANCEL)
  695. {
  696. // no more T.120
  697. g_pChatObj->LeaveT120();
  698. // Close chat
  699. ::T120_AppletStatus(APPLET_ID_CHAT, APPLET_CLOSING);
  700. ::DestroyWindow(m_hWnd);
  701. ::UnregisterClass(szMainClassName, g_hInstance);
  702. m_hWnd = NULL;
  703. PostQuitMessage(0);
  704. }
  705. DBGEXIT(CNmChatCtl::cmdFileExit);
  706. }
  707. void CNmChatCtl::cmdViewStatusBar(void)
  708. {
  709. DBGENTRY(CNmChatCtl::cmdViewStatusBar);
  710. RECT rect;
  711. GetClientRect(m_hWnd, &rect );
  712. ::ShowWindow(m_hwndSB, _IsStatusBarVisibleFlagSet() ? SW_HIDE : SW_SHOW);
  713. _Resize( 0, 0, rect.right, rect.bottom );
  714. RedrawWindow(m_hWnd, NULL, NULL, RDW_UPDATENOW | RDW_INVALIDATE);
  715. DBGEXIT(CNmChatCtl::cmdViewStatusBar);
  716. }
  717. //////////////////////////////////////////////////////////////////////////
  718. void CNmChatCtl::cmdViewEditWindow(void)
  719. {
  720. DBGENTRY(CNmChatCtl::cmdViewEditWindow);
  721. int iShowCommand = _IsEditWindowVisibleFlagSet() ? SW_HIDE : SW_SHOW;
  722. ::ShowWindow( m_hWndEdit, iShowCommand );
  723. ::ShowWindow( m_hWndSend, iShowCommand );
  724. ::ShowWindow( m_hWndStaticMessage, iShowCommand );
  725. ::ShowWindow( m_hWndStaticSendTo, iShowCommand );
  726. ::ShowWindow( m_hWndMemberList, iShowCommand );
  727. _CalculateFontMetrics();
  728. RECT rect;
  729. GetClientRect(m_hWnd, &rect );
  730. _Resize( 0, 0, rect.right, rect.bottom );
  731. RedrawWindow(m_hWnd, NULL, NULL, RDW_UPDATENOW | RDW_INVALIDATE);
  732. DBGEXIT(CNmChatCtl::cmdViewEditWindow);
  733. }
  734. void CNmChatCtl::cmdEditCut(void)
  735. {
  736. DBGENTRY(CNmChatCtl::cmdEditCut);
  737. ::SendMessage(m_hWndEdit, WM_CUT, 0, 0);
  738. DBGEXIT(CNmChatCtl::cmdEditCut);
  739. }
  740. void CNmChatCtl::cmdEditCopy(void)
  741. {
  742. DBGENTRY(CNmChatCtl::cmdEditCopy);
  743. HWND hwnd = ::GetFocus();
  744. if(hwnd == 0)
  745. {
  746. hwnd = m_hWndEdit;
  747. }
  748. ::SendMessage(hwnd, WM_COPY, 0, 0);
  749. DBGEXIT(CNmChatCtl::cmdEditCopy);
  750. }
  751. void CNmChatCtl::cmdEditPaste(void)
  752. {
  753. DBGENTRY(CNmChatCtl::cmdEditPaste);
  754. ::SendMessage(m_hWndEdit, WM_PASTE, 0, 0);
  755. DBGEXIT(CNmChatCtl::cmdEditPaste);
  756. }
  757. void CNmChatCtl::cmdEditClearAll(void)
  758. {
  759. DBGENTRY(CNmChatCtl::cmdEditClearAll);
  760. if( !_IsPrinting() )
  761. {
  762. ResetView();
  763. }
  764. DBGEXIT(CNmChatCtl::cmdEditClearAll);
  765. }
  766. void CNmChatCtl::cmdViewOptions(void)
  767. {
  768. DBGENTRY(CNmChatCtl::cmdViewOptions);
  769. if(m_pChatOptions == NULL)
  770. {
  771. DBG_SAVE_FILE_LINE
  772. m_pChatOptions = new CChatOptionsDlg( this );
  773. }
  774. ::DialogBox (g_hInstance,
  775. MAKEINTRESOURCE(IDD_CHAT_OPTIONS),
  776. m_hWnd,
  777. CChatOptionsDlg::_OptionsDlgProc);
  778. delete m_pChatOptions;
  779. m_pChatOptions = NULL;
  780. DBGEXIT(CNmChatCtl::cmdViewOptions);
  781. }
  782. void CNmChatCtl::cmdHelpHelpTopics(void)
  783. {
  784. DBGENTRY(CNmChatCtl::cmdHelpHelpTopics);
  785. ShowNmHelp(s_cszHtmlHelpFile);
  786. DBGEXIT(CNmChatCtl::cmdHelpHelpTopics);
  787. }
  788. void CNmChatCtl::cmdHelpAboutChat()
  789. {
  790. DBGENTRY(CNmChatCtl::cmdHelpAboutChat);
  791. ::DialogBox( g_hInstance,
  792. MAKEINTRESOURCE( IDD_CHAT_ABOUT ),
  793. m_hWnd,
  794. _AboutDlgProc );
  795. DBGEXIT(CNmChatCtl::cmdHelpAboutChat);
  796. }
  797. int CNmChatCtl::QueryEndSession()
  798. {
  799. DBGENTRY(CNmChatCtl::QueryEndSession);
  800. //
  801. // We may be shuting down, last good chance to save the position
  802. //
  803. _SaveWindowPosition();
  804. _SaveChatOptions();
  805. int iRet;
  806. {
  807. if( m_dwChatFlags & CHAT_FLAG_DIRTYBIT )
  808. {
  809. TCHAR szRes[MAX_PATH];
  810. TCHAR szRes2[MAX_PATH];
  811. iRet = ::MessageBox( m_hWnd,
  812. RES2T(IDS_SAVE_CHANGES_TO_CHAT_BEFORE_EXITING,szRes),
  813. RES2T(IDS_NETMEETING_CHAT,szRes2),
  814. MB_YESNOCANCEL | MB_ICONEXCLAMATION
  815. );
  816. if( IDCANCEL == iRet )
  817. {
  818. return iRet;
  819. }
  820. else if( IDYES == iRet )
  821. {
  822. if( m_lpszSaveFile && *m_lpszSaveFile )
  823. {
  824. // if we already have a save file name
  825. // we just save it....
  826. _Save();
  827. }
  828. else
  829. {
  830. iRet = _SaveAs();
  831. }
  832. }
  833. }
  834. }
  835. DBGEXIT(CNmChatCtl::QueryEndSession);
  836. return iRet;
  837. }
  838. STDMETHODIMP CNmChatCtl::OnMenuSelect( IN DWORD wParam, IN DWORD lParam )
  839. {
  840. DBGENTRY(CNmChatCtl::OnMenuSelect);
  841. HRESULT hr = S_OK;
  842. UINT fuFlags = HIWORD( wParam );
  843. if( !( ( 0xFFFF == fuFlags ) && ( NULL == lParam ) ) )
  844. {
  845. switch( LOWORD( wParam ) )
  846. {
  847. case ID_SEND_MESSAGE:
  848. case ID_FILE_SAVE:
  849. case ID_FILE_SAVEAS:
  850. case ID_FILE_PRINT:
  851. case ID_FILE_EXIT:
  852. case MENUPOS_FILE:
  853. OnInitMenuPopup( 0, MAKELPARAM( MENUPOS_FILE, 0 ));
  854. break;
  855. case ID_VIEW_STATUSBAR:
  856. case ID_VIEW_EDITWINDOW:
  857. case ID_VIEW_OPTIONS:
  858. case MENUPOS_VIEW:
  859. OnInitMenuPopup( 0, MAKELPARAM( MENUPOS_VIEW, 0 ));
  860. break;
  861. case ID_EDIT_CUT:
  862. case ID_EDIT_COPY:
  863. case ID_EDIT_PASTE:
  864. case ID_EDIT_CLEARALL:
  865. case MENUPOS_EDIT:
  866. OnInitMenuPopup( 0, MAKELPARAM( MENUPOS_EDIT, 0 ));
  867. break;
  868. case ID_HELP_HELPTOPICS:
  869. case ID_HELP_ABOUTCHAT:
  870. default:
  871. break;
  872. }
  873. OnMenuSelect(WM_MENUSELECT, wParam, lParam);
  874. }
  875. DBGEXIT_HR(CNmChatCtl::OnMenuSelect,hr);
  876. return hr;
  877. }
  878. LRESULT CNmChatCtl::OnContextMenu(short x, short y)
  879. {
  880. // pop it up
  881. OnInitMenuPopup(0, MENUPOS_EDIT);
  882. ::TrackPopupMenu(::GetSubMenu(m_hMenuShared, MENUPOS_EDIT), TPM_RIGHTALIGN | TPM_RIGHTBUTTON,
  883. x , y , 0, m_hWnd, NULL);
  884. return 0;
  885. }
  886. STDMETHODIMP CNmChatCtl::OnCommand( IN WPARAM wParam, IN LPARAM lParam )
  887. {
  888. DBGENTRY(CNmChatCtl::OnCommand);
  889. HRESULT hr = S_OK;
  890. if(m_hWndSend == (HWND)lParam)
  891. {
  892. OnSendClicked();
  893. return 0;
  894. }
  895. if((CBN_SETFOCUS == HIWORD(wParam) && m_hWndMemberList == (HWND)lParam) ||
  896. (EN_SETFOCUS == HIWORD(wParam) && m_hWndEdit == (HWND)lParam))
  897. {
  898. //
  899. // Deselect the text in the message window
  900. //
  901. CHARRANGE charRange;
  902. charRange.cpMin = m_cchBufferSize + 1;
  903. charRange.cpMax = m_cchBufferSize + 1;
  904. ::SendMessage( m_hWndMsg, EM_EXSETSEL, 0L, (LPARAM) &charRange );
  905. }
  906. switch( LOWORD( wParam ) )
  907. {
  908. case ID_SEND_MESSAGE: OnSendClicked(); break;
  909. case ID_FILE_SAVE: cmdFileSave(); break;
  910. case ID_FILE_SAVEAS: cmdFileSaveAs(); break;
  911. case ID_FILE_PRINT: cmdFilePrint(); break;
  912. case ID_FILE_EXIT: cmdFileExit(0); break;
  913. case ID_VIEW_STATUSBAR: cmdViewStatusBar(); break;
  914. case ID_EDIT_CUT: cmdEditCut(); break;
  915. case ID_EDIT_COPY: cmdEditCopy(); break;
  916. case ID_EDIT_PASTE: cmdEditPaste(); break;
  917. case ID_EDIT_CLEARALL: cmdEditClearAll(); break;
  918. case ID_VIEW_EDITWINDOW: cmdViewEditWindow(); break;
  919. case ID_VIEW_OPTIONS: cmdViewOptions (); break;
  920. case ID_HELP_HELPTOPICS: cmdHelpHelpTopics(); break;
  921. case ID_HELP_ABOUTCHAT: cmdHelpAboutChat(); break;
  922. }
  923. DBGEXIT_HR(CNmChatCtl::OnCommand,hr);
  924. return hr;
  925. }
  926. void CNmChatCtl::OnGetMinMaxInfo(LPMINMAXINFO lpmmi)
  927. {
  928. DBGENTRY(CNmChatCtl::OnGetMinMaxInfo);
  929. SIZE csFrame;
  930. csFrame.cx = ::GetSystemMetrics(SM_CXSIZEFRAME);
  931. csFrame.cy = ::GetSystemMetrics(SM_CYSIZEFRAME);
  932. lpmmi->ptMinTrackSize.y =
  933. csFrame.cy +
  934. GetSystemMetrics( SM_CYCAPTION ) +
  935. GetSystemMetrics( SM_CYMENU ) +
  936. DYP_CHAT_SEND * 2 + // At least 2 lines
  937. m_iStaticY + // Message:
  938. DYP_CHAT_SEND + // Edit box
  939. m_iStaticY + // Send to:
  940. ComboBoxEx_GetItemHeight(m_hWndMemberList, 0) + // ComboBox
  941. STATUSBAR_HEIGHT +
  942. csFrame.cy;
  943. lpmmi->ptMinTrackSize.x =
  944. csFrame.cx +
  945. m_iStaticLen * 2 +
  946. SPACING_DLU_X * m_iDLGUX +
  947. DXP_CHAT_SEND +
  948. csFrame.cx;
  949. // Retrieves the size of the work area on the primary display monitor. The work
  950. // area is the portion of the screen not obscured by the system taskbar or by
  951. // application desktop toolbars
  952. //
  953. RECT rcWorkArea;
  954. ::SystemParametersInfo( SPI_GETWORKAREA, 0, (&rcWorkArea), NULL );
  955. csFrame.cx = rcWorkArea.right - rcWorkArea.left;
  956. csFrame.cy = rcWorkArea.bottom - rcWorkArea.top;
  957. lpmmi->ptMaxPosition.x = 0;
  958. lpmmi->ptMaxPosition.y = 0;
  959. lpmmi->ptMaxSize.x = csFrame.cx;
  960. lpmmi->ptMaxSize.y = csFrame.cy;
  961. lpmmi->ptMaxTrackSize.x = csFrame.cx;
  962. lpmmi->ptMaxTrackSize.y = csFrame.cy;
  963. DBGEXIT(CNmChatCtl::OnGetMinMaxInfo);
  964. }
  965. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  966. // CNmChatCtl INmChatCtl implementation
  967. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  968. STDMETHODIMP CNmChatCtl::ResetView()
  969. {
  970. DBGENTRY(CNmChatCtl::ResetView());
  971. HRESULT hr;
  972. if( _IsPrinting() )
  973. {
  974. hr = E_FAIL;
  975. }
  976. else
  977. {
  978. ::SetWindowText( m_hWndMsg, TEXT(""));
  979. m_cchBufferSize = 0;
  980. m_cMessages = 0;
  981. CChatMessage::DeleteAll();
  982. m_dwChatFlags &= ~CHAT_FLAG_DIRTYBIT;
  983. hr = S_OK;
  984. }
  985. DBGEXIT_HR(CNmChatCtl::ResetView, hr);
  986. return hr;
  987. }
  988. void CNmChatCtl::_ReDisplayMessages()
  989. {
  990. DBGENTRY(CNmChatCtl::_ReDisplayMessages());
  991. SNDMSG( m_hWndMsg, WM_SETREDRAW, FALSE, 0 );
  992. ::SetWindowText( m_hWndMsg, TEXT(""));
  993. CChatMessage *pMsg = CChatMessage::get_head();
  994. while( pMsg != NULL )
  995. {
  996. _DisplayMsg( pMsg, FALSE );
  997. pMsg = pMsg->get_next();
  998. }
  999. SNDMSG( m_hWndMsg, WM_SETREDRAW, TRUE, 0 );
  1000. ::InvalidateRect( m_hWndMsg, NULL, INVALIDATE_BACKGROUND );
  1001. DBGEXIT(CNmChatCtl::_ReDisplayMessages);
  1002. }
  1003. CNmChatCtl::MSGSTYLE CNmChatCtl::get_MsgStyle()
  1004. {
  1005. return m_style;
  1006. }
  1007. STDMETHODIMP CNmChatCtl::put_MsgStyle( /*[in]*/ MSGSTYLE iStyle )
  1008. {
  1009. DBGENTRY(CNmChatCtl::put_MsgStyle);
  1010. HRESULT hr = S_OK;
  1011. DWORD dwStyle;
  1012. if( MSGSTYLE_2_LINE_WRAP == iStyle ||
  1013. MSGSTYLE_1_LINE_WRAP == iStyle )
  1014. {
  1015. dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_MULTILINE | ES_READONLY | \
  1016. ES_SAVESEL | ES_NOHIDESEL | ES_AUTOVSCROLL | WS_VSCROLL;
  1017. }
  1018. else if( MSGSTYLE_NO_WRAP == iStyle )
  1019. {
  1020. dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_MULTILINE | ES_READONLY | \
  1021. ES_SAVESEL | ES_NOHIDESEL | ES_AUTOVSCROLL | WS_VSCROLL | WS_HSCROLL | ES_AUTOVSCROLL;
  1022. }
  1023. else
  1024. {
  1025. hr = E_FAIL;
  1026. DBGEXIT_HR(CNmChatCtl::put_MsgStyle, hr);
  1027. return hr;
  1028. }
  1029. HWND hwndKill = m_hWndMsg;
  1030. m_hWndMsg = ::CreateWindowEx( WS_EX_CLIENTEDGE,
  1031. m_lpszRichEd,
  1032. NULL,
  1033. dwStyle,
  1034. 0,0,0,0,
  1035. m_hWnd,
  1036. NULL,
  1037. g_hInstance,
  1038. this );
  1039. ASSERT( m_hWndMsg );
  1040. ::SendMessage( m_hWndMsg, WM_SETFONT, (WPARAM)m_hMsgFonts[ CChatOptionsDlg::FONT_MSGOUT ], 0L );
  1041. ::SendMessage( m_hWndMsg, EM_AUTOURLDETECT, (WPARAM) TRUE, 0L );
  1042. ::SendMessage( m_hWndMsg, EM_SETBKGNDCOLOR, (WPARAM) TRUE, 0L );
  1043. ::SendMessage( m_hWndMsg, EM_SETEVENTMASK, 0L, (LPARAM) ENM_LINK );
  1044. ::SendMessage( m_hWndMsg, WM_PAINT, 0, 0);
  1045. m_style = iStyle;
  1046. _CalculateFontMetrics();
  1047. RECT rect;
  1048. GetClientRect(m_hWnd, &rect );
  1049. _Resize( 0, 0, rect.right, rect.bottom );
  1050. ::SendMessage( m_hWndMsg, EM_SETPARAFORMAT, 0, (LPARAM) &m_paraLine1 );
  1051. _ReDisplayMessages();
  1052. if( ::IsWindow( hwndKill ) )
  1053. {
  1054. ::DestroyWindow( hwndKill );
  1055. }
  1056. DBGEXIT_HR(CNmChatCtl::put_MsgStyle, hr);
  1057. return hr;
  1058. }
  1059. STDMETHODIMP CNmChatCtl::put_ShowName(/*[in]*/ short bUseName )
  1060. {
  1061. DBGENTRY(CNmChatCtl::put_ShowName);
  1062. m_bUseName = bUseName;
  1063. DBGEXIT_HR(CNmChatCtl::put_ShowName, S_OK);
  1064. return S_OK;
  1065. }
  1066. STDMETHODIMP CNmChatCtl::get_ShowName(/*[out]*/ short *pbUseName )
  1067. {
  1068. DBGENTRY(CNmChatCtl::get_ShowName);
  1069. HRESULT hr = S_OK;
  1070. if( NULL == pbUseName )
  1071. {
  1072. hr = E_POINTER;
  1073. }
  1074. else
  1075. {
  1076. *pbUseName = m_bUseName;
  1077. }
  1078. DBGEXIT_HR(CNmChatCtl::get_ShowName, hr);
  1079. return hr;
  1080. }
  1081. STDMETHODIMP CNmChatCtl::put_Date(/*[in]*/ short bUseDate )
  1082. {
  1083. DBGENTRY(CNmChatCtl::put_Date);
  1084. m_bUseDate = bUseDate;
  1085. DBGEXIT_HR(CNmChatCtl::put_Date, S_OK);
  1086. return S_OK;
  1087. }
  1088. STDMETHODIMP CNmChatCtl::get_Date(/*[out]*/ short *pbUseDate )
  1089. {
  1090. DBGENTRY(CNmChatCtl::get_Date);
  1091. HRESULT hr = S_OK;
  1092. if( NULL == pbUseDate )
  1093. {
  1094. hr = E_POINTER;
  1095. }
  1096. else
  1097. {
  1098. *pbUseDate = m_bUseDate;
  1099. }
  1100. DBGEXIT_HR(CNmChatCtl::get_Date, hr);
  1101. return hr;
  1102. }
  1103. STDMETHODIMP CNmChatCtl::put_Timestamp(/*[in]*/ short bUseTimeStamp )
  1104. {
  1105. DBGENTRY(CNmChatCtl::put_Timestamp);
  1106. m_bTimeStamp = bUseTimeStamp;
  1107. DBGEXIT_HR(CNmChatCtl::put_Timestamp, S_OK);
  1108. return S_OK;
  1109. }
  1110. STDMETHODIMP CNmChatCtl::get_Timestamp(/*[out]*/ short *pbUseTimeStamp )
  1111. {
  1112. DBGENTRY(CNmChatCtl::get_Timestamp);
  1113. HRESULT hr = S_OK;
  1114. if( NULL == pbUseTimeStamp )
  1115. {
  1116. hr = E_POINTER;
  1117. }
  1118. else
  1119. {
  1120. *pbUseTimeStamp = m_bTimeStamp;
  1121. }
  1122. DBGEXIT_HR(CNmChatCtl::get_Timestamp, hr);
  1123. return hr;
  1124. }
  1125. void CNmChatCtl::_Resize(int x, int y, int cx, int cy)
  1126. {
  1127. DBGENTRY(CNmChatCtl::_Resize);
  1128. if( _IsEditWindowVisibleFlagSet() )
  1129. {
  1130. int iStatusBarHeight = _IsStatusBarVisibleFlagSet() ? STATUSBAR_HEIGHT : 0;
  1131. int iMsgListY = MSGLIST_DLU_Y * m_iDLGUY;
  1132. int iBetweenX = SPACING_DLU_X * m_iDLGUX;
  1133. int iStaticHeight = m_iStaticY + STATIC_DLU_Y * m_iDLGUY;
  1134. int iStaticStart = STATIC_DLU_Y * m_iDLGUY;
  1135. HDWP hdwp = ::BeginDeferWindowPos(7);
  1136. ::DeferWindowPos(hdwp, m_hWndMsg, NULL,
  1137. 0,
  1138. 0,
  1139. cx,
  1140. cy-DYP_CHAT_SEND-iMsgListY-(iStaticHeight*2) - iStatusBarHeight,
  1141. SWP_NOZORDER);
  1142. ::DeferWindowPos(hdwp, m_hWndStaticMessage, NULL,
  1143. 0,
  1144. cy-DYP_CHAT_SEND-iMsgListY-iStaticHeight*2 + iStaticStart - iStatusBarHeight,
  1145. m_iStaticLen,
  1146. m_iStaticY,
  1147. SWP_NOZORDER);
  1148. ::DeferWindowPos(hdwp, m_hWndEdit, NULL,
  1149. 0,
  1150. cy-iMsgListY-iStaticHeight-DYP_CHAT_SEND - iStatusBarHeight,
  1151. cx - DXP_CHAT_SEND - iBetweenX,
  1152. DYP_CHAT_SEND,
  1153. SWP_NOZORDER);
  1154. ::DeferWindowPos(hdwp, m_hWndSend, NULL,
  1155. cx-DXP_CHAT_SEND,
  1156. cy-iMsgListY-iStaticHeight-DYP_CHAT_SEND - iStatusBarHeight,
  1157. DXP_CHAT_SEND,
  1158. DYP_CHAT_SEND,
  1159. SWP_NOZORDER);
  1160. ::DeferWindowPos(hdwp, m_hWndStaticSendTo, NULL,
  1161. 0,
  1162. cy-iMsgListY-iStaticHeight + iStaticStart - iStatusBarHeight,
  1163. m_iStaticLen,
  1164. m_iStaticY,
  1165. SWP_NOZORDER);
  1166. ::DeferWindowPos(hdwp, m_hWndMemberList, NULL,
  1167. 0,
  1168. cy-iMsgListY - iStatusBarHeight,
  1169. cx,
  1170. ComboBoxEx_GetItemHeight(m_hWndMemberList, 0),
  1171. SWP_NOZORDER);
  1172. RECT rect;
  1173. ::GetClientRect(m_hWnd, &rect);
  1174. rect.top = rect.bottom - iStatusBarHeight;
  1175. ::DeferWindowPos(hdwp, m_hwndSB, NULL,
  1176. rect.left, rect.top,
  1177. rect.right - rect.left,
  1178. rect.bottom - rect.top,
  1179. SWP_NOZORDER);
  1180. ::EndDeferWindowPos(hdwp);
  1181. }
  1182. else
  1183. {
  1184. int iStatusBarHeight = _IsStatusBarVisibleFlagSet() ? STATUSBAR_HEIGHT : 0;
  1185. ::MoveWindow(m_hWndMsg,
  1186. 0, 0, cx, cy - iStatusBarHeight,
  1187. TRUE);
  1188. }
  1189. DBGEXIT(CNmChatCtl::_Resize);
  1190. }
  1191. void CNmChatCtl::_LoadIconImages(void)
  1192. {
  1193. DBGENTRY(CNmChatCtl::_LoadIconImages);
  1194. COLORREF crTOOLBAR_MASK_COLOR = ( RGB( 255, 0, 255 ) );
  1195. if( NULL == m_himlIconSmall )
  1196. {
  1197. m_himlIconSmall = ImageList_Create(DXP_ICON_SMALL, DYP_ICON_SMALL, ILC_MASK, 1, 0);
  1198. if (NULL != m_himlIconSmall)
  1199. {
  1200. HBITMAP hBmp = ::LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_CHAT_SMALL_ICON_IMAGES));
  1201. if (NULL != hBmp)
  1202. {
  1203. ImageList_AddMasked(m_himlIconSmall, hBmp, crTOOLBAR_MASK_COLOR);
  1204. ::DeleteObject(hBmp);
  1205. }
  1206. }
  1207. }
  1208. DBGEXIT(CNmChatCtl::_LoadIconImages);
  1209. }
  1210. void CNmChatCtl::_FreeIconImages(void)
  1211. {
  1212. DBGENTRY(CNmChatCtl::_FreeIconImages);
  1213. if (NULL != m_himlIconSmall)
  1214. {
  1215. ImageList_Destroy(m_himlIconSmall);
  1216. m_himlIconSmall = NULL;
  1217. }
  1218. DBGEXIT(CNmChatCtl::_FreeIconImages);
  1219. }
  1220. HRESULT CNmChatCtl::_SendChatText(void)
  1221. {
  1222. DBGENTRY(CNmChatCtl::_SendChatText);
  1223. HRESULT hr = S_OK;
  1224. TCHAR szMsg[CCHMAX_CHAT_MSG];
  1225. // Get the text line
  1226. int cb = (int)::SendMessage(m_hWndEdit, WM_GETTEXT, (WPARAM) CCHMAX(szMsg), (LPARAM) szMsg);
  1227. if (0 != cb)
  1228. {
  1229. if (cb == 1)
  1230. {
  1231. szMsg[1] = ' ';
  1232. szMsg[2] = 0;
  1233. cb++;
  1234. }
  1235. // Delete the text in the edit box ( remember it is stored in szMsg )
  1236. ::SendMessage(m_hWndEdit, EM_SETSEL, (WPARAM) 0, (LPARAM)-1);
  1237. ::SendMessage(m_hWndEdit, WM_SETTEXT, (WPARAM) 0, (LPARAM) "");
  1238. ::SetFocus(m_hWndEdit); // reset the focus if we actually sent something
  1239. MEMBER_CHANNEL_ID *pMemberID = (MEMBER_CHANNEL_ID*)_GetSelectedMember();
  1240. MEMBER_ID memberID;
  1241. TCHAR szName[MAX_PATH*2];
  1242. szName[0] = '\0';
  1243. CChatMessage::CHAT_MSGTYPE cmtype;
  1244. LPTSTR szPerson = NULL;
  1245. if( pMemberID == 0 )
  1246. {
  1247. cmtype = CChatMessage::MSG_SAY;
  1248. memberID = MAKE_MEMBER_ID(0, g_pChatObj->m_broadcastChannel);
  1249. }
  1250. else
  1251. {
  1252. // Use the whisper
  1253. memberID = MAKE_MEMBER_ID(pMemberID->nNodeId, pMemberID->nWhisperId);
  1254. cmtype = CChatMessage::MSG_WHISPER;
  1255. ULONG cb = T120_GetNodeName(g_pChatObj->m_nConfID, pMemberID->nNodeId, szName, MAX_PATH*2);
  1256. }
  1257. _DisplayMsg( new CChatMessage( szName, szMsg, cmtype ) );
  1258. if (g_pChatObj)
  1259. {
  1260. // Allocate a temporary buffer
  1261. BYTE * pb = new BYTE[CB_NM2_HDR + (CCHMAX_CHAT_MSG * sizeof(WCHAR))];
  1262. if (NULL != pb)
  1263. {
  1264. BYTE * pbData = pb+CB_NM2_HDR;
  1265. // Initialize the header
  1266. ZeroMemory(pb, CB_NM2_HDR);
  1267. * ((LPDWORD) pb) = CB_NM2_HDR;
  1268. cb++; // include final null
  1269. #ifdef UNICODE
  1270. lstrcpy(pbData, szMsg);
  1271. #else
  1272. cb = MultiByteToWideChar(CP_ACP, 0, szMsg, cb, (LPWSTR) pbData, CCHMAX_CHAT_MSG);
  1273. cb *= 2; // adjust for UNICODE
  1274. #endif //!UNICODE
  1275. // Add special prefix
  1276. cb += CB_NM2_HDR;
  1277. hr = g_pChatObj->SendData(GET_USER_ID_FROM_MEMBER_ID(memberID), cb, (BYTE*)pb);
  1278. delete pb;
  1279. }
  1280. else
  1281. {
  1282. ERROR_OUT(("Out of memory!!!"));
  1283. hr = E_OUTOFMEMORY;
  1284. }
  1285. }
  1286. }
  1287. else
  1288. {
  1289. // There was no chat text
  1290. }
  1291. DBGEXIT_HR(CNmChatCtl::_SendChatText, hr);
  1292. return hr;
  1293. }
  1294. void CNmChatCtl::_DataReceived(ULONG uSize, LPBYTE pb, T120ChannelID destinationID, T120UserID senderID)
  1295. {
  1296. DBGENTRY(CNmChatCtl::DataReceived);
  1297. ASSERT(uSize > CNmChatCtl::CB_NM2_HDR);
  1298. LPTSTR psz = (LPTSTR) (pb + *(LPDWORD) pb); // skip past header
  1299. #ifndef UNICODE
  1300. // Convert UNICODE to ANSI
  1301. char sz[CNmChatCtl::CCHMAX_CHAT_MSG];
  1302. WideCharToMultiByte(CP_ACP, 0, (LPWSTR) psz, -1, sz, CNmChatCtl::
  1303. CCHMAX_CHAT_MSG, NULL, NULL);
  1304. psz = sz;
  1305. #endif //
  1306. TCHAR szPerson[MAX_PATH*2] = "\0";
  1307. T120NodeID nodeID = ComboBoxEx_GetNodeIDFromSendID(m_hWndMemberList, senderID );
  1308. if (0 == nodeID)
  1309. {
  1310. nodeID = ComboBoxEx_GetNodeIDFromPrivateSendID(m_hWndMemberList, senderID);
  1311. }
  1312. ULONG cb = T120_GetNodeName(g_pChatObj->m_nConfID, nodeID, szPerson, MAX_PATH*2);
  1313. // Display the message to the chat window
  1314. _DisplayMsg(new CChatMessage( szPerson, psz,
  1315. ( destinationID == GET_USER_ID_FROM_MEMBER_ID(g_pChatObj->m_MyMemberID)) ?
  1316. CChatMessage::MSG_WHISPER_FROM_OTHER : CChatMessage::MSG_FROM_OTHER ));
  1317. DBGEXIT_HR(CNmChannelEventSink::DataReceived, S_OK);
  1318. }
  1319. inline void CNmChatCtl::_Write_Msg( LPTSTR pszText )
  1320. {
  1321. ASSERT( NULL != pszText );
  1322. ::SendMessage( m_hWndMsg, EM_REPLACESEL, (WPARAM) FALSE, (WPARAM) pszText );
  1323. m_cchBufferSize += lstrlen( pszText );
  1324. }
  1325. inline void CNmChatCtl::_Write_Msg_Range_Format( LPTSTR pszText, CHARRANGE& charRange, CHARFORMAT& chatFormat )
  1326. {
  1327. charRange.cpMin = m_cchBufferSize;
  1328. charRange.cpMax = m_cchBufferSize;
  1329. ::SendMessage( m_hWndMsg, EM_EXSETSEL, 0L, (LPARAM) &charRange );
  1330. ::SendMessage( m_hWndMsg, EM_SETCHARFORMAT, (WPARAM)SCF_SELECTION, (LPARAM) &chatFormat );
  1331. _Write_Msg( pszText );
  1332. }
  1333. inline void CNmChatCtl::_Write_Date_And_Time( LPTSTR pszText, CHARRANGE& charRange, CHARFORMAT& chatFormat, CChatMessage *pChatMsg )
  1334. {
  1335. if( m_bUseDate )
  1336. {
  1337. wsprintf( pszText, TEXT("%s\t"), pChatMsg->get_date() );
  1338. _Write_Msg_Range_Format( pszText, charRange, chatFormat ) ;
  1339. }
  1340. if( m_bTimeStamp )
  1341. {
  1342. wsprintf( pszText, TEXT("%s\t"), pChatMsg->get_time() );
  1343. _Write_Msg_Range_Format( pszText, charRange, chatFormat ) ;
  1344. }
  1345. }
  1346. inline void CNmChatCtl::_Write_Name( LPTSTR pszText, CHARRANGE& charRange, CHARFORMAT& chatFormat, CChatMessage *pChatMsg )
  1347. {
  1348. if( m_bUseName )
  1349. {
  1350. wsprintf( pszText, TEXT("%s\t"), pChatMsg->get_person() );
  1351. _Write_Msg_Range_Format( pszText, charRange, chatFormat );
  1352. }
  1353. }
  1354. inline void CNmChatCtl::_Write_Own_Name( LPTSTR pszText, CHARRANGE& charRange, CHARFORMAT& chatFormat )
  1355. {
  1356. if( m_bUseName )
  1357. {
  1358. if(m_lpszOwnName == NULL)
  1359. {
  1360. RegEntry re(ISAPI_CLIENT_KEY, HKEY_CURRENT_USER);
  1361. LPCTSTR pcszName = re.GetString(REGVAL_ULS_NAME);
  1362. DBG_SAVE_FILE_LINE
  1363. m_lpszOwnName = new TCHAR[lstrlen(pcszName) + 1];
  1364. wsprintf( m_lpszOwnName, TEXT("%s"),pcszName);
  1365. }
  1366. wsprintf( pszText, TEXT("%s\t"), m_lpszOwnName );
  1367. _Write_Msg_Range_Format( pszText, charRange, chatFormat );
  1368. }
  1369. }
  1370. inline void CNmChatCtl::_Write_Message( LPTSTR pszText, CHARRANGE& charRange, CHARFORMAT& chatFormat, CChatMessage *pChatMsg )
  1371. {
  1372. _Write_Msg_Range_Format( pChatMsg->get_message(), charRange, chatFormat );
  1373. _Write_Msg_Range_Format( m_lpszRichEdEOL, charRange, chatFormat );
  1374. }
  1375. inline void CNmChatCtl::_Write_Private_In( LPTSTR pszText, CHARRANGE& charRange, CHARFORMAT& chatFormat, CChatMessage *pChatMsg )
  1376. {
  1377. wsprintf( pszText, TEXT("[%s]"), m_szPrivate );
  1378. _Write_Msg_Range_Format( pszText, charRange, chatFormat );
  1379. _Write_Message( pszText, charRange, chatFormat, pChatMsg );
  1380. }
  1381. inline void CNmChatCtl::_Write_Private_Out( LPTSTR pszText, CHARRANGE& charRange, CHARFORMAT& chatFormat, CChatMessage *pChatMsg )
  1382. {
  1383. wsprintf( pszText, TEXT("[%s %s %s] "), m_szPrivate, m_szTo, pChatMsg->get_person() );
  1384. _Write_Msg_Range_Format( pszText, charRange, chatFormat );
  1385. _Write_Message( pszText, charRange, chatFormat, pChatMsg );
  1386. }
  1387. inline void CNmChatCtl::_Write_New_Line_If_Needed( CHARRANGE& charRange, CHARFORMAT& chatFormat )
  1388. {
  1389. if( MSGSTYLE_2_LINE_WRAP == m_style )
  1390. {
  1391. _Write_Msg_Range_Format( m_lpszRichEdEOL, charRange, chatFormat );
  1392. ::SendMessage( m_hWndMsg, EM_SETPARAFORMAT, 0, (LPARAM) &m_paraLine2 );
  1393. ::SendMessage( m_hWndMsg, EM_GETPARAFORMAT, 0, (LPARAM) &m_paraLine2 );
  1394. }
  1395. }
  1396. inline void CNmChatCtl::_AddFontToCharFormat( CHARFORMAT& chatFormat, int i )
  1397. {
  1398. chatFormat.dwMask |= CFM_COLOR | CFM_ALLCAPS | CFM_CHARSET | CFM_BOLD | CFM_FACE | CFM_ITALIC | CFM_SIZE | CFM_STRIKEOUT | CFM_UNDERLINE;
  1399. chatFormat.crTextColor = m_hMsgColors[ i ];
  1400. if( m_hMsgLogFonts[i].lfWeight >= FW_BOLD )
  1401. {
  1402. chatFormat.dwEffects |= CFE_BOLD;
  1403. }
  1404. if( m_hMsgLogFonts[i].lfItalic )
  1405. {
  1406. chatFormat.dwEffects |= CFE_ITALIC;
  1407. }
  1408. if( m_hMsgLogFonts[i].lfUnderline )
  1409. {
  1410. chatFormat.dwEffects |= CFE_UNDERLINE;
  1411. }
  1412. if( m_hMsgLogFonts[i].lfStrikeOut )
  1413. {
  1414. chatFormat.dwEffects |= CFE_STRIKEOUT;
  1415. }
  1416. chatFormat.yHeight = 20 * _Points_From_LogFontHeight( m_hMsgLogFonts[i].lfHeight, m_hWnd );
  1417. chatFormat.bCharSet = m_hMsgLogFonts[i].lfCharSet;
  1418. chatFormat.bPitchAndFamily = m_hMsgLogFonts[i].lfPitchAndFamily;
  1419. lstrcpy( chatFormat.szFaceName, m_hMsgLogFonts[i].lfFaceName );
  1420. }
  1421. void CNmChatCtl::_DisplayMsg( CChatMessage *pChatMsg, BOOL bBatchRedraw /*= TRUE*/ )
  1422. {
  1423. DBGENTRY(CNmChatCtl::_DisplayMsg);
  1424. if( pChatMsg != NULL && !pChatMsg->IsValid() )
  1425. {
  1426. ERROR_OUT(( TEXT("CNmChatCtl::_DisplayMsg passed invalid message") ));
  1427. return;
  1428. }
  1429. TCHAR pszText[CCHMAX_CHAT_MSG];
  1430. CHARRANGE charRange;
  1431. //
  1432. // Start at the end of the last message
  1433. //
  1434. charRange.cpMin = m_cchBufferSize + 1;
  1435. charRange.cpMax = m_cchBufferSize + 1;
  1436. ::SendMessage( m_hWndMsg, EM_EXSETSEL, 0L, (LPARAM) &charRange );
  1437. CHARFORMAT chatFormat;
  1438. ZeroMemory( &chatFormat, sizeof( chatFormat ) );
  1439. chatFormat.cbSize = sizeof( chatFormat );
  1440. ::SendMessage( m_hWndMsg, EM_SETPARAFORMAT, 0, (LPARAM) &m_paraLine1 );
  1441. ::SendMessage( m_hWndMsg, EM_GETPARAFORMAT, 0, (LPARAM) &m_paraLine1 );
  1442. CChatMessage::CHAT_MSGTYPE msgType = pChatMsg->get_type();
  1443. switch( msgType )
  1444. {
  1445. case CChatMessage::MSG_WHISPER_FROM_OTHER:
  1446. case CChatMessage::MSG_FROM_OTHER:
  1447. case CChatMessage::MSG_WHISPER:
  1448. case CChatMessage::MSG_SAY:
  1449. {
  1450. if( bBatchRedraw )
  1451. {
  1452. SNDMSG( m_hWndMsg, WM_SETREDRAW, FALSE, 0 );
  1453. }
  1454. switch( msgType )
  1455. {
  1456. case CChatMessage::MSG_WHISPER_FROM_OTHER:
  1457. {
  1458. _AddFontToCharFormat( chatFormat, CChatOptionsDlg::FONT_PRIVATEIN );
  1459. break;
  1460. }
  1461. case CChatMessage::MSG_FROM_OTHER:
  1462. {
  1463. _AddFontToCharFormat( chatFormat, CChatOptionsDlg::FONT_MSGIN );
  1464. break;
  1465. }
  1466. case CChatMessage::MSG_WHISPER:
  1467. {
  1468. _AddFontToCharFormat( chatFormat, CChatOptionsDlg::FONT_PRIVATEOUT );
  1469. break;
  1470. }
  1471. case CChatMessage::MSG_SAY:
  1472. {
  1473. _AddFontToCharFormat( chatFormat, CChatOptionsDlg::FONT_MSGOUT );
  1474. break;
  1475. }
  1476. }
  1477. _Write_Date_And_Time( pszText, charRange, chatFormat, pChatMsg );
  1478. if( pChatMsg->IsIncoming() )
  1479. {
  1480. _Write_Name( pszText, charRange, chatFormat, pChatMsg );
  1481. }
  1482. else
  1483. {
  1484. _Write_Own_Name( pszText, charRange, chatFormat );
  1485. }
  1486. _Write_New_Line_If_Needed( charRange, chatFormat );
  1487. if( !pChatMsg->IsPrivate() )
  1488. {
  1489. _Write_Message( pszText, charRange, chatFormat, pChatMsg );
  1490. }
  1491. else if( pChatMsg->IsIncoming() )
  1492. {
  1493. _Write_Private_In( pszText, charRange, chatFormat, pChatMsg );
  1494. }
  1495. else
  1496. {
  1497. _Write_Private_Out( pszText, charRange, chatFormat, pChatMsg );
  1498. }
  1499. // Update message count
  1500. m_cMessages++;
  1501. m_dwChatFlags |= CHAT_FLAG_DIRTYBIT;
  1502. if( bBatchRedraw )
  1503. {
  1504. SNDMSG( m_hWndMsg, WM_SETREDRAW, TRUE, 0 );
  1505. ::InvalidateRect( m_hWndMsg, NULL, INVALIDATE_BACKGROUND );
  1506. }
  1507. break;
  1508. }
  1509. case CChatMessage::MSG_SYSTEM:
  1510. {
  1511. _AddFontToCharFormat( chatFormat, CChatOptionsDlg::FONT_MSGSYSTEM );
  1512. _Write_Message( pszText, charRange, chatFormat, pChatMsg );
  1513. break;
  1514. }
  1515. default:
  1516. {
  1517. ERROR_OUT(( TEXT("CNmChatCtl::_DisplayMsg - Unknown Message Type") ));
  1518. return;
  1519. break;
  1520. }
  1521. }
  1522. DBGEXIT(CNmChatCtl::_DisplayMsg);
  1523. }
  1524. HRESULT CNmChatCtl::_AddEveryoneInChat()
  1525. {
  1526. DBGENTRY( CNmChatCtl::_AddEveryoneInChat );
  1527. ASSERT( m_hWndMemberList );
  1528. HRESULT hr = S_OK;
  1529. int iImage = II_PERSON_PERSON;
  1530. int iItem = 0;
  1531. TCHAR szName[MAX_PATH];
  1532. TCHAR szRes[MAX_PATH];
  1533. lstrcpy( szName, RES2T( IDS_FILTER_ALL, szRes ) );
  1534. COMBOBOXEXITEM cbexi;
  1535. ClearStruct( &cbexi );
  1536. cbexi.mask = CBEIF_LPARAM | CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE ;
  1537. cbexi.iItem = iItem;
  1538. cbexi.pszText = szName;
  1539. cbexi.cchTextMax = lstrlen(cbexi.pszText);
  1540. cbexi.iSelectedImage = iImage;
  1541. cbexi.iImage = iImage;
  1542. cbexi.lParam = (LPARAM) NULL;
  1543. ComboBoxEx_InsertItem(m_hWndMemberList, &cbexi);
  1544. ComboBoxEx_SetCurSel( m_hWndMemberList, 0 );
  1545. DBGEXIT_HR( CNmChatCtl::_AddEveryoneInChat, hr );
  1546. return hr;
  1547. }
  1548. HBITMAP CNmChatCtl::_GetHBITMAP( DWORD dwID )
  1549. {
  1550. DBGENTRY(CNmChatCtl::_GetHBITMAP);
  1551. HBITMAP hb = static_cast<HBITMAP>( LoadImage(g_hInstance, MAKEINTRESOURCE(dwID), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE));
  1552. DBGEXIT(CNmChatCtl::_GetHBITMAP);
  1553. return hb;
  1554. }
  1555. // Delete item iIndex from the m_hWndMemberList list view and free the
  1556. // pMember that is stored in the lParam of that item...
  1557. HRESULT CNmChatCtl::_DeleteMemberListItem( int iIndex )
  1558. {
  1559. DBGENTRY(CNmChatCtl::_DeleteMemberListItem);
  1560. HRESULT hr = S_OK;
  1561. TCHAR szName[MAX_PATH];
  1562. COMBOBOXEXITEM cbexi;
  1563. ClearStruct( &cbexi );
  1564. cbexi.iItem = iIndex;
  1565. cbexi.mask = CBEIF_LPARAM | CBEIF_TEXT;
  1566. cbexi.pszText = szName;
  1567. cbexi.cchTextMax = CCHMAX(szName);
  1568. // Find the item iIndex and get the Text and lParam data
  1569. if( ComboBoxEx_GetItem( m_hWndMemberList, &cbexi ) )
  1570. {
  1571. if( CB_ERR == ComboBoxEx_DeleteItem(m_hWndMemberList, iIndex) )
  1572. {
  1573. WARNING_OUT(( "Could not delete %s from ComboBox", cbexi.pszText ));
  1574. }
  1575. }
  1576. else
  1577. {
  1578. // There was an error...
  1579. WARNING_OUT(("There was an error getting the list view item..."));
  1580. DWORD dwErr = GetLastError();
  1581. hr = HRESULT_FROM_WIN32( dwErr );
  1582. }
  1583. DBGEXIT_HR(CNmChatCtl::_DeleteMemberListItem, hr);
  1584. return hr;
  1585. }
  1586. void CNmChatCtl::_DeleteAllListItems( void )
  1587. {
  1588. DBGENTRY(CNmChatCtl::_DeleteAllListItems);
  1589. int cItems = ComboBoxEx_GetCount( m_hWndMemberList );
  1590. while( cItems-- )
  1591. { // Delete the first item in the list...
  1592. int IndexOfFirstItemInList = 0;
  1593. _DeleteMemberListItem( IndexOfFirstItemInList );
  1594. }
  1595. ComboBoxEx_SetCurSel( m_hWndMemberList, 0 );
  1596. DBGEXIT(CNmChatCtl::_DeleteAllListItems);
  1597. }
  1598. HRESULT CNmChatCtl::_GetOwnName()
  1599. {
  1600. DBGENTRY( CNmChatCtl::_GetOwnName );
  1601. HRESULT hr = E_FAIL;
  1602. DBGEXIT_HR( CNmChatCtl::_GetOwnName, hr );
  1603. return( hr );
  1604. }
  1605. void CNmChatCtl::_UpdateContainerCaption( void )
  1606. {
  1607. DBGENTRY(CNmChatCtl::_UpdateContainerCaption);
  1608. TCHAR szCaption[MAX_PATH * 2];
  1609. TCHAR szCaption2[MAX_PATH * 2];
  1610. UINT captionID;
  1611. UINT statusID;
  1612. if (! g_pChatObj->IsInConference())
  1613. {
  1614. captionID = IDS_CHAT_NOT_IN_CALL_WINDOW_CAPTION;
  1615. statusID = IDS_CHAT_STATUS_CHAT_NOT_ACTIVE;
  1616. }
  1617. else
  1618. {
  1619. captionID = IDS_CHAT_IN_CALL_WINDOW_CAPTION;
  1620. statusID = IDS_CHAT_STATUS_CHAT_ACTIVE;
  1621. }
  1622. ::LoadString(g_hInstance, captionID, szCaption, sizeof(szCaption) );
  1623. wsprintf(szCaption2, szCaption, m_cOtherMembers);
  1624. ::SetWindowText(m_hWnd, szCaption2);
  1625. _SetContainerStatusText( statusID );
  1626. DBGEXIT(CNmChatCtl::_UpdateContainerCaption);
  1627. }
  1628. void CNmChatCtl::_CalculateFontMetrics()
  1629. {
  1630. DBGENTRY(CNmChatCtl::_CalculateFontMetrics);
  1631. ASSERT( m_hWndMsg );
  1632. ///// Get Info for RichEdit Box
  1633. CHARFORMAT chfmt2;
  1634. int yMaxHeightInTwips = 0;
  1635. for( int i = 0; i < CChatOptionsDlg::FONT_COUNT; i++ )
  1636. {
  1637. ZeroMemory( &chfmt2, sizeof( chfmt2 ) );
  1638. _AddFontToCharFormat( chfmt2, i );
  1639. if( yMaxHeightInTwips < chfmt2.yHeight )
  1640. {
  1641. yMaxHeightInTwips = chfmt2.yHeight;
  1642. }
  1643. }
  1644. TEXTMETRIC textmex;
  1645. HDC hdc = ::GetDC( m_hWndMsg );
  1646. ::GetTextMetrics( hdc, &textmex );
  1647. ::ReleaseDC( m_hWndMsg, hdc );
  1648. /*
  1649. * Average Width of Char in Twips Average Width of Chars Logical Unit
  1650. * ------------------------------ = -----------------------------------
  1651. * Height of Char in Twips Height of Char in Logical Unit
  1652. *
  1653. */
  1654. int iAveWidthInTwips = yMaxHeightInTwips * textmex.tmAveCharWidth / textmex.tmHeight;
  1655. int iMaxWidthInTwips = yMaxHeightInTwips * textmex.tmMaxCharWidth / textmex.tmHeight;
  1656. // Set the tabs on the two paragraph format rich edit things
  1657. ZeroMemory( &m_paraLine1, sizeof( m_paraLine1 ) );
  1658. m_paraLine1.cbSize = sizeof( m_paraLine1 );
  1659. m_paraLine1.dwMask = PFM_OFFSET | PFM_TABSTOPS | PFM_STARTINDENT | PFM_RIGHTINDENT ;
  1660. ZeroMemory( &m_paraLine2, sizeof( m_paraLine2 ) );
  1661. m_paraLine2.cbSize = sizeof( m_paraLine2 );
  1662. m_paraLine2.dwMask = PFM_OFFSET | PFM_TABSTOPS | PFM_STARTINDENT | PFM_RIGHTINDENT ;
  1663. m_paraLine2.dxStartIndent = MULTILINE_MSG_OFFSET * iAveWidthInTwips;
  1664. int iDelta = 0;
  1665. if( m_bUseDate )
  1666. {
  1667. iDelta = DATE_EXTRA + GetDateFormat(
  1668. LOCALE_USER_DEFAULT, // locale for which date is to be formatted
  1669. 0, // flags specifying function options
  1670. NULL, // time to be formatted
  1671. NULL, // time format string
  1672. NULL, // buffer for storing formatted string
  1673. 0 // size, in bytes or characters, of the buffer
  1674. );
  1675. iDelta *= iAveWidthInTwips;
  1676. if( m_paraLine1.cTabCount )
  1677. {
  1678. m_paraLine1.rgxTabs[ m_paraLine1.cTabCount ] = m_paraLine1.rgxTabs[ m_paraLine1.cTabCount -1 ] + iDelta;
  1679. }
  1680. else
  1681. {
  1682. m_paraLine1.rgxTabs[ 0 ] = iDelta;
  1683. }
  1684. m_paraLine1.cTabCount++;
  1685. }
  1686. if( m_bTimeStamp )
  1687. {
  1688. iDelta = TIME_EXTRA + GetTimeFormat(
  1689. LOCALE_USER_DEFAULT, // locale for which date is to be formatted
  1690. 0, // flags specifying function options
  1691. NULL, // time to be formatted
  1692. NULL, // time format string
  1693. NULL, // buffer for storing formatted string
  1694. 0 // size, in bytes or characters, of the buffer
  1695. );
  1696. iDelta *= iAveWidthInTwips;
  1697. if( m_paraLine1.cTabCount )
  1698. {
  1699. m_paraLine1.rgxTabs[ m_paraLine1.cTabCount ] = m_paraLine1.rgxTabs[ m_paraLine1.cTabCount -1 ] + iDelta;
  1700. }
  1701. else
  1702. {
  1703. m_paraLine1.rgxTabs[ 0 ] = iDelta;
  1704. }
  1705. m_paraLine1.cTabCount++;
  1706. }
  1707. if( m_bUseName )
  1708. {
  1709. iDelta = (MAX_NAME + NAME_EXTRA) * iAveWidthInTwips;
  1710. if( m_paraLine1.cTabCount )
  1711. {
  1712. m_paraLine1.rgxTabs[ m_paraLine1.cTabCount ] = m_paraLine1.rgxTabs[ m_paraLine1.cTabCount -1 ] + iDelta;
  1713. }
  1714. else
  1715. {
  1716. m_paraLine1.rgxTabs[ 0 ] = iDelta;
  1717. }
  1718. m_paraLine1.cTabCount++;
  1719. }
  1720. if( m_paraLine1.cTabCount )
  1721. {
  1722. m_paraLine1.dxOffset = m_paraLine1.rgxTabs[ m_paraLine1.cTabCount -1 ];
  1723. }
  1724. DBGEXIT(CNmChatCtl::_CalculateFontMetrics );
  1725. }
  1726. void CNmChatCtl::_SetContainerStatusText( UINT uID )
  1727. {
  1728. DBGENTRY(CNmChatCtl::_SetContainerStatusText);
  1729. TCHAR szStatus[MAX_RESOURCE_STRING_LEN] = "";
  1730. NmCtlLoadString( uID, szStatus, CchMax(szStatus) );
  1731. ::SetWindowText(m_hwndSB, szStatus);
  1732. DBGEXIT(CNmChatCtl::_SetContainerStatusText);
  1733. }
  1734. // Get the selected member from the m_hWndMemberList list view...
  1735. MEMBER_ID CNmChatCtl::_GetSelectedMember()
  1736. {
  1737. DBGENTRY(CNmChatCtl::_GetSelectedMember);
  1738. COMBOBOXEXITEM cbexi;
  1739. ClearStruct( &cbexi );
  1740. cbexi.mask = CBEIF_LPARAM;
  1741. // Find the matching item
  1742. if( CB_ERR == ( cbexi.iItem = ComboBoxEx_GetCurSel(m_hWndMemberList ) ) )
  1743. {
  1744. ATLTRACE(("CNmChatCtl::_GetSelectedMember - no selection?\n"));
  1745. DBGEXIT(CNmChatCtl::_GetSelectedMember);
  1746. return 0;
  1747. }
  1748. ComboBoxEx_GetItem( m_hWndMemberList, &cbexi );
  1749. MEMBER_ID memberID = (MEMBER_ID)( cbexi.lParam );
  1750. DBGEXIT(CNmChatCtl::_GetSelectedMember);
  1751. return memberID;
  1752. }
  1753. HRESULT CNmChatCtl::_AddMember(MEMBER_CHANNEL_ID *pMemberID)
  1754. {
  1755. DBGENTRY(CNmChatCtl::_AddMember);
  1756. HRESULT hr = S_OK;
  1757. int iImage;
  1758. int iItem = -1;
  1759. TCHAR szName[MAX_PATH];
  1760. if (GET_NODE_ID_FROM_MEMBER_ID(g_pChatObj->m_MyMemberID) != pMemberID->nNodeId)
  1761. {
  1762. TCHAR szName[MAX_PATH*2];
  1763. ULONG cb = T120_GetNodeName(g_pChatObj->m_nConfID, pMemberID->nNodeId, szName, MAX_PATH*2);
  1764. iImage = II_USER;
  1765. COMBOBOXEXITEM cbexi;
  1766. ClearStruct( &cbexi );
  1767. cbexi.mask = CBEIF_LPARAM | CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE ;
  1768. cbexi.iItem = iItem;
  1769. cbexi.pszText = szName;
  1770. cbexi.cchTextMax = lstrlen(cbexi.pszText);
  1771. cbexi.iSelectedImage = iImage;
  1772. cbexi.iImage = iImage;
  1773. cbexi.lParam = (LPARAM) pMemberID;
  1774. ComboBoxEx_InsertItem(m_hWndMemberList, &cbexi);
  1775. }
  1776. DBGEXIT_HR(CNmChatCtl::_AddMember, hr);
  1777. return hr;
  1778. }
  1779. HRESULT CNmChatCtl::_RemoveMember(MEMBER_CHANNEL_ID *pMemberID)
  1780. {
  1781. DBGENTRY(CNmChatCtl::_RemoveMember);
  1782. HRESULT hr = S_OK;
  1783. int iItem = ComboBoxEx_FindMember( m_hWndMemberList, -1, pMemberID);
  1784. if( -1 != iItem )
  1785. {
  1786. _DeleteMemberListItem( iItem );
  1787. }
  1788. else
  1789. {
  1790. WARNING_OUT(("Could not find the specified item..."));
  1791. hr = HRESULT_FROM_WIN32(GetLastError());
  1792. }
  1793. DBGEXIT_HR(CNmChatCtl::_RemoveMember, hr);
  1794. return hr;
  1795. }
  1796. HRESULT CNmChatCtl::_SetMenuItemCheck( UINT idItem, BOOL bChecked /* = true */ )
  1797. {
  1798. DBGENTRY(CNmChatCtl::_SetMenuItemCheck);
  1799. HRESULT hr = S_OK;
  1800. if( m_hMenuShared )
  1801. {
  1802. MENUITEMINFO mii;
  1803. ClearStruct(&mii);
  1804. mii.cbSize = sizeof( MENUITEMINFO );
  1805. mii.fMask = MIIM_STATE;
  1806. mii.fState = bChecked ? MFS_CHECKED : MFS_UNCHECKED;
  1807. if( !SetMenuItemInfo(m_hMenuShared, idItem, FALSE, &mii) )
  1808. {
  1809. hr = HRESULT_FROM_WIN32(GetLastError());
  1810. }
  1811. }
  1812. else
  1813. {
  1814. hr = E_UNEXPECTED;
  1815. }
  1816. DBGEXIT_HR(CNmChatCtl::_SetMenuItemCheck,hr);
  1817. return hr;
  1818. }
  1819. bool CNmChatCtl::_IsEditWindowVisibleFlagSet(void)
  1820. {
  1821. return ( ::IsWindow( m_hWndEdit ) && IsWindowVisible(m_hWndEdit));
  1822. }
  1823. bool CNmChatCtl::_IsStatusBarVisibleFlagSet(void)
  1824. {
  1825. return ( ::IsWindow( m_hwndSB ) && IsWindowVisible(m_hwndSB));
  1826. }
  1827. int CNmChatCtl::_SaveAs()
  1828. {
  1829. int iRet = 0;
  1830. if( NULL == m_lpszSaveFile )
  1831. {
  1832. DBG_SAVE_FILE_LINE
  1833. m_lpszSaveFile = new TCHAR[ MAX_PATH ];
  1834. ASSERT( m_lpszSaveFile );
  1835. ZeroMemory( m_lpszSaveFile, sizeof( m_lpszSaveFile ) );
  1836. }
  1837. if( SUCCEEDED( SaveDialog( m_lpszSaveFile, OFN_HIDEREADONLY | OFN_CREATEPROMPT, &m_wFileOffset ) ) )
  1838. {
  1839. // Since the file name has changed, we are dirty....
  1840. m_dwChatFlags |= CHAT_FLAG_DIRTYBIT;
  1841. _Save();
  1842. }
  1843. else
  1844. {
  1845. iRet = IDCANCEL;
  1846. }
  1847. return iRet;
  1848. }
  1849. LRESULT CNmChatCtl::SaveDialog(LPTSTR lpszFile, DWORD dwFlags, LPWORD pnFileOffset )
  1850. {
  1851. DBGENTRY(CNmChatCtl::SaveDialog)
  1852. HRESULT hr = S_OK;
  1853. TCHAR szFilter[MAX_PATH];
  1854. TCHAR szDefExt[MAX_PATH];
  1855. if( SUCCEEDED ( hr = _GetNmAppletFileOpenFilter( szFilter, CCHMAX( szFilter ), szDefExt, CCHMAX( szDefExt ) ) ) )
  1856. {
  1857. ConvertSzCh(szFilter);
  1858. OPENFILENAME ofn;
  1859. ClearStruct( &ofn );
  1860. ofn.lStructSize = sizeof( OPENFILENAME );
  1861. ofn.hwndOwner = m_hWnd;
  1862. ofn.lpstrFilter = szFilter;
  1863. ofn.lpstrFile = lpszFile;
  1864. ofn.nMaxFile = MAX_PATH;
  1865. ofn.lpstrDefExt = szDefExt;
  1866. ofn.Flags = dwFlags;
  1867. if( !GetSaveFileName( &ofn ) )
  1868. {
  1869. hr = E_FAIL;
  1870. }
  1871. else
  1872. {
  1873. *pnFileOffset = ofn.nFileOffset;
  1874. }
  1875. }
  1876. DBGEXIT_HR(CNmChatCtl::SaveDialog,hr)
  1877. return hr;
  1878. }
  1879. void CNmChatCtl::_SaveWindowPosition()
  1880. {
  1881. RECT rectWindow;
  1882. // If we are not maximized
  1883. if (!::IsZoomed(m_hWnd) && !::IsIconic(m_hWnd))
  1884. {
  1885. // Get the new window rectangle
  1886. ::GetWindowRect(m_hWnd, &rectWindow);
  1887. // Write the new option values to file
  1888. _SetWindowRectOption(&rectWindow);
  1889. }
  1890. }
  1891. void CNmChatCtl::_SaveChatOptions()
  1892. {
  1893. RegEntry reWnd( CHAT_KEY, HKEY_CURRENT_USER );
  1894. reWnd.SetValue(OPT_MAIN_INFORMATION_DISPLAY_NAME, m_bUseName);
  1895. reWnd.SetValue(OPT_MAIN_INFORMATION_DISPLAY_TIME, m_bTimeStamp);
  1896. reWnd.SetValue(OPT_MAIN_INFORMATION_DISPLAY_DATE, m_bUseDate);
  1897. reWnd.SetValue(OPT_MAIN_MESSAGE_FORMAT, m_style);
  1898. for (int i = 0; i < CChatOptionsDlg::FONT_COUNT; i++ )
  1899. {
  1900. reWnd.SetValue( OPT_FONT_COLOR[i], &m_hMsgColors[i], sizeof(COLORREF));
  1901. reWnd.SetValue( OPT_FONT_FORMAT[i], &m_hMsgLogFonts[i], sizeof(LOGFONT));
  1902. }
  1903. }
  1904. BOOL CNmChatCtl::_LoadChatOptions()
  1905. {
  1906. BOOL fRet = FALSE;
  1907. int i;
  1908. RegEntry reWnd(CHAT_KEY, HKEY_CURRENT_USER);
  1909. LPVOID pData;
  1910. for (i = 0; i < CChatOptionsDlg::FONT_COUNT; i++ )
  1911. {
  1912. if (reWnd.GetBinary(OPT_FONT_COLOR[i], &pData) != sizeof(COLORREF))
  1913. break;
  1914. ::CopyMemory(&m_hMsgColors[i], pData, sizeof(COLORREF));
  1915. if (reWnd.GetBinary(OPT_FONT_FORMAT[i], &pData) != sizeof(LOGFONT))
  1916. break;
  1917. ::CopyMemory(&m_hMsgLogFonts[i], pData, sizeof(LOGFONT));
  1918. }
  1919. if (i == CChatOptionsDlg::FONT_COUNT)
  1920. {
  1921. for (i = 0; i < CChatOptionsDlg::FONT_COUNT; i++ )
  1922. {
  1923. m_hMsgFonts[ i ] = CreateFontIndirect( &m_hMsgLogFonts[i] );
  1924. }
  1925. m_bUseName = (BOOL)reWnd.GetNumber(OPT_MAIN_INFORMATION_DISPLAY_NAME);
  1926. m_bTimeStamp = (BOOL)reWnd.GetNumber(OPT_MAIN_INFORMATION_DISPLAY_TIME);
  1927. m_bUseDate = (BOOL)reWnd.GetNumber(OPT_MAIN_INFORMATION_DISPLAY_DATE);
  1928. m_style = (CNmChatCtl::eMsgStyles)reWnd.GetNumber(OPT_MAIN_MESSAGE_FORMAT);
  1929. fRet = TRUE;
  1930. }
  1931. return fRet;
  1932. }
  1933. void CNmChatCtl::_Save()
  1934. {
  1935. ASSERT( m_lpszSaveFile );
  1936. if( 0 == (m_dwChatFlags & CHAT_FLAG_DIRTYBIT) )
  1937. {
  1938. return;
  1939. }
  1940. TCHAR szDrive[ MAX_PATH ];
  1941. lstrcpyn( szDrive, m_lpszSaveFile, m_wFileOffset + 1 );
  1942. if( !FDirExists( szDrive ) )
  1943. {
  1944. TCHAR szBuffer[ 2 * MAX_PATH ];
  1945. TCHAR szRes[MAX_PATH];
  1946. wsprintf( szBuffer, RES2T( IDS_CHAT_CREATE_DIRECTORY, szRes ), szDrive );
  1947. if( IDYES == MessageBox(m_hWnd, szBuffer, RES2T(IDS_CHAT_DOCUMENTNAME, szRes), MB_YESNO | MB_ICONQUESTION ) )
  1948. {
  1949. if( !FEnsureDirExists( szDrive ) )
  1950. {
  1951. wsprintf( szBuffer, RES2T( IDS_CHAT_COULD_NOT_CREATE_DIR, szRes ), szDrive );
  1952. MessageBox(m_hWnd, szBuffer, RES2T(IDS_CHAT_DOCUMENTNAME, szRes), MB_OK | MB_ICONEXCLAMATION );
  1953. return;
  1954. }
  1955. }
  1956. }
  1957. HANDLE hFile = CreateFile( m_lpszSaveFile,
  1958. GENERIC_WRITE,
  1959. 0,
  1960. NULL,
  1961. CREATE_ALWAYS,
  1962. 0,
  1963. NULL );
  1964. if( INVALID_HANDLE_VALUE == hFile )
  1965. {
  1966. DWORD dw = GetLastError();
  1967. switch( dw )
  1968. {
  1969. case ERROR_ACCESS_DENIED:
  1970. {
  1971. TCHAR szBuffer[ 2 * MAX_PATH ];
  1972. TCHAR szRes[MAX_PATH];
  1973. wsprintf( szBuffer, RES2T( IDS_CHAT_SAVE_ACCESS_DENIED, szRes ), m_lpszSaveFile );
  1974. MessageBox(m_hWnd, szBuffer, RES2T(IDS_CHAT_DOCUMENTNAME, szRes), MB_OK | MB_ICONEXCLAMATION );
  1975. break;
  1976. }
  1977. default:
  1978. {
  1979. TCHAR szBuffer[ 2 * MAX_PATH ];
  1980. TCHAR szRes[MAX_PATH];
  1981. wsprintf( szBuffer, RES2T( IDS_CHAT_SAVE_FAILED, szRes ), m_lpszSaveFile );
  1982. MessageBox(m_hWnd, szBuffer, RES2T(IDS_CHAT_DOCUMENTNAME, szRes), MB_OK | MB_ICONEXCLAMATION );
  1983. break;
  1984. }
  1985. }
  1986. }
  1987. else
  1988. {
  1989. LPTSTR szHeader1 = TEXT("<HTML>\n<HEAD>\n<TITLE>");
  1990. LPTSTR szHeader2 = TEXT("</TITLE>\n</HEAD>\n<BODY BGCOLOR=\"white\" TEXT=\"black\">\n<TABLE BORDER=1>");
  1991. LPTSTR szEnd = TEXT("</TABLE>\n</BODY>\n</HTML>\n");
  1992. LPTSTR szStartRow = TEXT("<TR><TD>");
  1993. LPTSTR szEndRow = TEXT("</TD></TR>");
  1994. LPTSTR szSplitRow = TEXT("</TD><TD>");
  1995. TCHAR szPrivateTo[ MAX_PATH ];
  1996. TCHAR szPrivateFrom[ MAX_PATH ];
  1997. TCHAR szBuffer[ CCHMAX_CHAT_MSG ];
  1998. DWORD dwWritten;
  1999. NmCtlLoadString(IDS_CHAT_SAVE_PRIVATE_TO, szPrivateTo, MAX_PATH);
  2000. NmCtlLoadString(IDS_CHAT_SAVE_PRIVATE, szPrivateFrom, MAX_PATH);
  2001. WriteFile( hFile, szHeader1, lstrlen( szHeader1 ), &dwWritten, NULL );
  2002. NmCtlLoadString(IDS_CHAT_DOCUMENTNAME, szBuffer, MAX_PATH);
  2003. WriteFile( hFile, szBuffer, lstrlen( szBuffer ), &dwWritten, NULL );
  2004. WriteFile( hFile, szHeader2, lstrlen( szHeader2 ), &dwWritten, NULL );
  2005. CChatMessage *pMsg = CChatMessage::get_head();
  2006. while( pMsg != NULL )
  2007. {
  2008. CChatMessage::CHAT_MSGTYPE style = pMsg->get_type();
  2009. switch( style )
  2010. {
  2011. case CChatMessage::MSG_SAY:
  2012. case CChatMessage::MSG_WHISPER:
  2013. {
  2014. WriteFile( hFile, szStartRow, lstrlen( szStartRow ), &dwWritten, NULL );
  2015. lstrcpy( szBuffer, m_lpszOwnName );
  2016. WriteFile( hFile, szBuffer, lstrlen( szBuffer ), &dwWritten, NULL );
  2017. WriteFile( hFile, szSplitRow, lstrlen( szSplitRow ), &dwWritten, NULL );
  2018. lstrcpy( szBuffer, pMsg->get_date() );
  2019. WriteFile( hFile, szBuffer, lstrlen( szBuffer ), &dwWritten, NULL );
  2020. WriteFile( hFile, szSplitRow, lstrlen( szSplitRow ), &dwWritten, NULL );
  2021. lstrcpy( szBuffer, pMsg->get_time() );
  2022. WriteFile( hFile, szBuffer, lstrlen( szBuffer ), &dwWritten, NULL );
  2023. WriteFile( hFile, szSplitRow, lstrlen( szSplitRow ), &dwWritten, NULL );
  2024. if( CChatMessage::MSG_WHISPER == style )
  2025. {
  2026. wsprintf( szBuffer, szPrivateTo, pMsg->get_person() );
  2027. WriteFile( hFile, szBuffer, lstrlen( szBuffer ), &dwWritten, NULL );
  2028. }
  2029. lstrcpy( szBuffer, pMsg->get_message() );
  2030. WriteFile( hFile, szBuffer, lstrlen( szBuffer ), &dwWritten, NULL );
  2031. WriteFile( hFile, szEndRow, lstrlen( szEndRow ), &dwWritten, NULL );
  2032. break;
  2033. }
  2034. case CChatMessage::MSG_FROM_OTHER:
  2035. case CChatMessage::MSG_WHISPER_FROM_OTHER:
  2036. {
  2037. WriteFile( hFile, szStartRow, lstrlen( szStartRow ), &dwWritten, NULL );
  2038. lstrcpy( szBuffer, pMsg->get_person() );
  2039. WriteFile( hFile, szBuffer, lstrlen( szBuffer ), &dwWritten, NULL );
  2040. WriteFile( hFile, szSplitRow, lstrlen( szSplitRow ), &dwWritten, NULL );
  2041. lstrcpy( szBuffer, pMsg->get_date() );
  2042. WriteFile( hFile, szBuffer, lstrlen( szBuffer ), &dwWritten, NULL );
  2043. WriteFile( hFile, szSplitRow, lstrlen( szSplitRow ), &dwWritten, NULL );
  2044. lstrcpy( szBuffer, pMsg->get_time() );
  2045. WriteFile( hFile, szBuffer, lstrlen( szBuffer ), &dwWritten, NULL );
  2046. WriteFile( hFile, szSplitRow, lstrlen( szSplitRow ), &dwWritten, NULL );
  2047. if( CChatMessage::MSG_WHISPER_FROM_OTHER == style )
  2048. {
  2049. WriteFile( hFile, szPrivateFrom, lstrlen( szPrivateFrom ), &dwWritten, NULL );
  2050. }
  2051. lstrcpy( szBuffer, pMsg->get_message() );
  2052. WriteFile( hFile, szBuffer, lstrlen( szBuffer ), &dwWritten, NULL );
  2053. WriteFile( hFile, szEndRow, lstrlen( szEndRow ), &dwWritten, NULL );
  2054. break;
  2055. }
  2056. default:
  2057. {
  2058. break;
  2059. }
  2060. }
  2061. pMsg = pMsg->get_next();
  2062. };
  2063. WriteFile( hFile, szEnd, lstrlen( szEnd ), &dwWritten, NULL );
  2064. CloseHandle( hFile );
  2065. m_dwChatFlags &= ~CHAT_FLAG_DIRTYBIT;
  2066. }
  2067. }
  2068. inline BOOL CNmChatCtl::_IsPrinting()
  2069. {
  2070. return( m_dwChatFlags & CHAT_PRINT_FLAG_PRINTING );
  2071. }
  2072. // From: KB Article ID: Q129860
  2073. // Modified by t-ivanl
  2074. void CNmChatCtl::_PrintIt(HDC hPrinterDC )
  2075. {
  2076. DBGENTRY(CNmChatCtl::_PrintIt);
  2077. FORMATRANGE fr;
  2078. int nHorizRes = GetDeviceCaps(hPrinterDC, HORZRES);
  2079. int nVertRes = GetDeviceCaps(hPrinterDC, VERTRES);
  2080. int nLogPixelsX = GetDeviceCaps(hPrinterDC, LOGPIXELSX);
  2081. int nLogPixelsY = GetDeviceCaps(hPrinterDC, LOGPIXELSY);
  2082. LONG lTextLength = 0; // Length of document.
  2083. LONG lTextPrinted = 0; // Amount of document printed.
  2084. TCHAR lpszDateOrTime[ MAX_PATH ];
  2085. TCHAR lpszHeader[ MAX_PATH ];
  2086. RECT rcPrintLoc;
  2087. // Ensure the printer DC is in MM_TEXT mode.
  2088. SetMapMode ( hPrinterDC, MM_TEXT );
  2089. // Rendering to the same DC we are measuring.
  2090. ZeroMemory(&fr, sizeof(fr));
  2091. fr.hdc = fr.hdcTarget = hPrinterDC;
  2092. // Set up the page.
  2093. fr.rcPage.left = fr.rcPage.top = 0;
  2094. fr.rcPage.right = (nHorizRes/nLogPixelsX) * TWIPSPERINCH;
  2095. fr.rcPage.bottom = (nVertRes/nLogPixelsY) * TWIPSPERINCH;
  2096. // Set up 1" margins all around.
  2097. fr.rc.left = fr.rcPage.left + TWIPSPERINCH;
  2098. fr.rc.top = fr.rcPage.top + TWIPSPERINCH;
  2099. fr.rc.right = fr.rcPage.right - TWIPSPERINCH;
  2100. fr.rc.bottom = fr.rcPage.bottom - TWIPSPERINCH;
  2101. // Default the range of text to print as the entire document.
  2102. fr.chrg.cpMin = 0;
  2103. fr.chrg.cpMax = -1;
  2104. // Set up the print job (standard printing stuff here).
  2105. DOCINFO di;
  2106. ZeroMemory(&di, sizeof(di));
  2107. di.cbSize = sizeof(DOCINFO);
  2108. // Set the document name
  2109. DBG_SAVE_FILE_LINE
  2110. LPTSTR lpszDocName = new TCHAR[ MAX_PATH ];
  2111. ASSERT( lpszDocName );
  2112. NmCtlLoadString(IDS_CHAT_DOCUMENTNAME, lpszDocName, MAX_PATH);
  2113. di.lpszDocName = lpszDocName;
  2114. NmCtlLoadString(IDS_CHAT_HEADER, lpszHeader, MAX_PATH);
  2115. GetDateFormat( LOCALE_USER_DEFAULT, 0, NULL, NULL, lpszDateOrTime, CCHMAX( lpszDateOrTime ) );
  2116. lstrcat( lpszHeader, lpszDateOrTime );
  2117. lstrcat( lpszHeader, TEXT(" " ) );
  2118. GetTimeFormat( LOCALE_USER_DEFAULT, 0, NULL, NULL, lpszDateOrTime, CCHMAX( lpszDateOrTime ) );
  2119. lstrcat( lpszHeader, lpszDateOrTime );
  2120. GETTEXTLENGTHEX txtLength;
  2121. txtLength.flags = GTL_NUMCHARS | GTL_PRECISE;
  2122. txtLength.codepage = CP_ACP;
  2123. int bufferSize = (int)::SendMessage( m_hWndMsg, EM_GETTEXTLENGTHEX, (WPARAM)&txtLength, 0 );
  2124. if(bufferSize == E_INVALIDARG)
  2125. {
  2126. return;
  2127. }
  2128. lTextLength =bufferSize;
  2129. if( lTextLength > 1 )
  2130. {
  2131. m_hWndPrint = ::CreateDialog( g_hInstance,
  2132. MAKEINTRESOURCE( IDD_CHAT_PRINT ),
  2133. m_hWnd,
  2134. _PrintDlgProc );
  2135. ASSERT( m_hWndPrint );
  2136. SetAbortProc( hPrinterDC, _AbortProc );
  2137. // Start the document.
  2138. StartDoc(hPrinterDC, &di);
  2139. while( (lTextPrinted < lTextLength) && (0 == (CHAT_PRINT_FLAG_ABORT & m_dwChatFlags) ) )
  2140. {
  2141. // Start the page.
  2142. StartPage(hPrinterDC);
  2143. // New Header print code for bugfix #29365 [mmaddin].
  2144. rcPrintLoc.left = nLogPixelsX;
  2145. rcPrintLoc.top = nLogPixelsY / 2;
  2146. rcPrintLoc.right = fr.rc.right;
  2147. rcPrintLoc.bottom = fr.rc.bottom;
  2148. DrawText( hPrinterDC, lpszHeader, lstrlen( lpszHeader ), &rcPrintLoc, 0);
  2149. // Print as much text as can fit on a page. The return value is the
  2150. // index of the first character on the next page.
  2151. lTextPrinted = (LONG)::SendMessage(m_hWndMsg,
  2152. EM_FORMATRANGE,
  2153. FALSE,
  2154. (LPARAM)&fr);
  2155. if( 0 != lTextPrinted )
  2156. {
  2157. ::SendMessage(m_hWndMsg, EM_DISPLAYBAND, 0, (LPARAM)&fr.rc);
  2158. }
  2159. // Print last page.
  2160. EndPage(hPrinterDC);
  2161. if(lTextPrinted < fr.chrg.cpMin)
  2162. {
  2163. break;
  2164. }
  2165. // If there is more text to print, adjust the range of characters to
  2166. // start printing at the first character of the next page.
  2167. if( 0 == lTextPrinted )
  2168. {
  2169. break;
  2170. }
  2171. else if (lTextPrinted < lTextLength)
  2172. {
  2173. fr.chrg.cpMin = lTextPrinted;
  2174. fr.chrg.cpMax = -1;
  2175. }
  2176. }
  2177. // Tell the control to release cached information.
  2178. ::SendMessage(m_hWndMsg, EM_FORMATRANGE, 0, (LPARAM)NULL);
  2179. EndDoc(hPrinterDC);
  2180. }
  2181. delete [] lpszDocName;
  2182. EndDialog( m_hWndPrint, 0 );
  2183. DBGEXIT(CNmChatCtl::_PrintIt);
  2184. }
  2185. HRESULT CNmChatCtl::_Print()
  2186. {
  2187. DBGENTRY(CNmChatCtl::_Print);
  2188. HRESULT hr = E_FAIL;
  2189. if( 0 == ( CHAT_PRINT_FLAG_PRINTDLG_INITIALIZED & m_dwChatFlags ) )
  2190. {
  2191. ZeroMemory( &m_PrintDlg, sizeof( m_PrintDlg ) );
  2192. m_PrintDlg.lStructSize = sizeof( m_PrintDlg );
  2193. m_PrintDlg.hwndOwner = m_hWnd;
  2194. m_PrintDlg.Flags = PD_ALLPAGES | PD_NOPAGENUMS | PD_NOSELECTION | PD_RETURNDC | PD_DISABLEPRINTTOFILE;
  2195. m_dwChatFlags |= CHAT_PRINT_FLAG_PRINTDLG_INITIALIZED;
  2196. }
  2197. BOOL b;
  2198. if( FALSE != (b = PrintDlg( &m_PrintDlg ) ) )
  2199. {
  2200. ms_pThis = this;
  2201. _PrintIt( m_PrintDlg.hDC );
  2202. ms_pThis = NULL;
  2203. hr = S_OK;
  2204. }
  2205. DBGEXIT_HR(CNmChatCtl::_Print, hr);
  2206. return hr;
  2207. }
  2208. BOOL CALLBACK CNmChatCtl::_AbortProc( HDC hdcPrinter, int iCode )
  2209. {
  2210. MSG msg;
  2211. while( (0 == (CHAT_PRINT_FLAG_ABORT & ms_pThis->m_dwChatFlags) ) &&
  2212. PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
  2213. {
  2214. if( NULL == ms_pThis->m_hWndPrint ||
  2215. !::IsDialogMessage( ms_pThis->m_hWndPrint, &msg ) )
  2216. {
  2217. TranslateMessage( &msg );
  2218. DispatchMessage( &msg );
  2219. }
  2220. }
  2221. return(0 == (CHAT_PRINT_FLAG_ABORT & ms_pThis->m_dwChatFlags) );
  2222. }
  2223. INT_PTR CALLBACK CNmChatCtl::_PrintDlgProc( HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam )
  2224. {
  2225. switch( uiMsg )
  2226. {
  2227. case WM_INITDIALOG:
  2228. {
  2229. return TRUE;
  2230. break;
  2231. }
  2232. case WM_COMMAND:
  2233. {
  2234. switch( LOWORD( wParam ) )
  2235. {
  2236. case IDCANCEL:
  2237. {
  2238. ms_pThis->m_dwChatFlags |= CHAT_PRINT_FLAG_ABORT;
  2239. //EndDialog( hDlg, CHAT_PRINT_FLAG_ABORT );
  2240. return TRUE;
  2241. }
  2242. }
  2243. }
  2244. }
  2245. return FALSE;
  2246. }
  2247. INT_PTR CALLBACK CNmChatCtl::_AboutDlgProc( HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam )
  2248. {
  2249. switch( uiMsg )
  2250. {
  2251. case WM_INITDIALOG:
  2252. {
  2253. TCHAR szFormat[256];
  2254. TCHAR szVersion[512];
  2255. ::GetDlgItemText(hDlg, IDC_CHAT_ABOUT_VERSION, szFormat, 256);
  2256. wsprintf(szVersion, szFormat, VER_PRODUCTRELEASE_STR,
  2257. VER_PRODUCTVERSION_STR);
  2258. ::SetDlgItemText(hDlg, IDC_CHAT_ABOUT_VERSION, szVersion);
  2259. return TRUE;
  2260. break;
  2261. }
  2262. case WM_QUIT:
  2263. case WM_COMMAND:
  2264. {
  2265. EndDialog( hDlg, IDOK );
  2266. return TRUE;
  2267. }
  2268. }
  2269. return FALSE;
  2270. }
  2271. INT_PTR CALLBACK CChatOptionsDlg::_OptionsDlgProc( HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam )
  2272. {
  2273. switch(uiMsg)
  2274. {
  2275. case WM_INITDIALOG:
  2276. g_pChatWindow->m_pChatOptions->OnInit(hDlg);
  2277. break;
  2278. case WM_HELP:
  2279. g_pChatWindow->m_pChatOptions->OnHelp(lParam);
  2280. break;
  2281. case WM_CONTEXTMENU:
  2282. g_pChatWindow->m_pChatOptions->OnHelpWhatsThis(wParam);
  2283. break;
  2284. case WM_COMMAND:
  2285. g_pChatWindow->m_pChatOptions->OnCommand(wParam);
  2286. break;
  2287. }
  2288. return 0;
  2289. }
  2290. void CChatOptionsDlg::OnCommand(WPARAM wParam)
  2291. {
  2292. switch( LOWORD( wParam ) )
  2293. {
  2294. case IDOK:
  2295. OnOkClicked();
  2296. break;
  2297. case IDCANCEL:
  2298. OnCancelClicked();
  2299. break;
  2300. case IDC_FONT_MSGOUT:
  2301. case IDC_FONT_MSGIN:
  2302. case IDC_FONT_PRIVATEOUT:
  2303. case IDC_FONT_PRIVATEIN:
  2304. OnFontClicked(LOWORD( wParam ));
  2305. break;
  2306. }
  2307. }
  2308. CChatOptionsDlg::CChatOptionsDlg( CNmChatCtl *pChatCtl )
  2309. : m_pChatCtl( pChatCtl )
  2310. {
  2311. }
  2312. void CChatOptionsDlg::_DisplayFontNameAndSize( int iFont )
  2313. {
  2314. TCHAR szBuffer[ MAX_PATH ];
  2315. TCHAR szRes[MAX_PATH];
  2316. ASSERT( iFont < FONT_COUNT );
  2317. wsprintf( szBuffer, RES2T( IDS_CHAT_OPTIONS_FONT_FORMAT,szRes ),
  2318. _Points_From_LogFontHeight( m_hMsgLogFonts[iFont].lfHeight, m_pChatCtl->GetHandle() ),
  2319. m_hMsgLogFonts[iFont].lfFaceName );
  2320. HWND hwndEdit = NULL;
  2321. switch( iFont )
  2322. {
  2323. case FONT_MSGOUT:
  2324. {
  2325. hwndEdit = GetDlgItem(m_hOptionsDlg, IDC_EDIT_MSGOUT );
  2326. break;
  2327. }
  2328. case FONT_MSGIN:
  2329. {
  2330. hwndEdit = GetDlgItem(m_hOptionsDlg, IDC_EDIT_MSGIN );
  2331. break;
  2332. }
  2333. case FONT_PRIVATEOUT:
  2334. {
  2335. hwndEdit = GetDlgItem(m_hOptionsDlg, IDC_EDIT_PRIVATEOUT );
  2336. break;
  2337. }
  2338. case FONT_PRIVATEIN:
  2339. {
  2340. hwndEdit = GetDlgItem(m_hOptionsDlg, IDC_EDIT_PRIVATEIN );
  2341. break;
  2342. }
  2343. }
  2344. ::SetWindowText( hwndEdit, szBuffer );
  2345. }
  2346. LRESULT CChatOptionsDlg::OnInit(HWND hDlg)
  2347. {
  2348. m_hOptionsDlg = hDlg;
  2349. for( int i = 0; i < FONT_COUNT; i++ )
  2350. {
  2351. m_hMsgLogFonts[ i ] = m_pChatCtl->m_hMsgLogFonts[ i ];
  2352. m_hMsgColors[ i ] = m_pChatCtl->m_hMsgColors[ i ];
  2353. m_bDirtyFonts[ i ] = FALSE;
  2354. _DisplayFontNameAndSize( i );
  2355. }
  2356. ::SendMessage( GetDlgItem(m_hOptionsDlg, IDC_INCLUDE_NAME ),
  2357. BM_SETCHECK,
  2358. (WPARAM)m_pChatCtl->m_bUseName,
  2359. 0L );
  2360. ::SetFocus( GetDlgItem(m_hOptionsDlg, IDC_INCLUDE_NAME ));
  2361. ::SendMessage( GetDlgItem(m_hOptionsDlg, IDC_INCLUDE_DATE ),
  2362. BM_SETCHECK,
  2363. (WPARAM)m_pChatCtl->m_bUseDate,
  2364. 0L );
  2365. ::SendMessage( GetDlgItem(m_hOptionsDlg, IDC_INCLUDE_TIME ),
  2366. BM_SETCHECK,
  2367. (WPARAM)m_pChatCtl->m_bTimeStamp,
  2368. 0L );
  2369. switch( m_pChatCtl->m_style )
  2370. {
  2371. case CNmChatCtl::MSGSTYLE_2_LINE_WRAP:
  2372. ::SendMessage( GetDlgItem(m_hOptionsDlg, IDR_NEW_LINE ),
  2373. BM_SETCHECK,
  2374. TRUE,
  2375. 0L );
  2376. break;
  2377. case CNmChatCtl::MSGSTYLE_1_LINE_WRAP:
  2378. ::SendMessage( GetDlgItem(m_hOptionsDlg, IDR_SAME_LINE ),
  2379. BM_SETCHECK,
  2380. TRUE,
  2381. 0L );
  2382. break;
  2383. case CNmChatCtl::MSGSTYLE_NO_WRAP:
  2384. ::SendMessage( GetDlgItem(m_hOptionsDlg, IDR_SINGLE_LINE ),
  2385. BM_SETCHECK,
  2386. TRUE,
  2387. 0L );
  2388. break;
  2389. }
  2390. return 0L;
  2391. }
  2392. LRESULT CChatOptionsDlg::OnHelp(LPARAM lParam)
  2393. {
  2394. DoHelp(lParam, _mpIdHelpChatOptions);
  2395. return 0L;
  2396. }
  2397. LRESULT CChatOptionsDlg::OnHelpWhatsThis(WPARAM wParam)
  2398. {
  2399. DoHelpWhatsThis(wParam, _mpIdHelpChatOptions);
  2400. return 0L;
  2401. }
  2402. LRESULT CChatOptionsDlg::OnOkClicked()
  2403. {
  2404. BOOL bChanged = FALSE;
  2405. // View Fields
  2406. BOOL bVal = (BOOL)::SendMessage( GetDlgItem(m_hOptionsDlg, IDC_INCLUDE_NAME ),
  2407. BM_GETCHECK,
  2408. 0L,
  2409. 0L );
  2410. bChanged = ( !m_pChatCtl->m_bUseName == !bVal ) ? bChanged : TRUE;
  2411. m_pChatCtl->m_bUseName = (short)bVal;
  2412. bVal = (BOOL)::SendMessage( GetDlgItem(m_hOptionsDlg, IDC_INCLUDE_TIME ),
  2413. BM_GETCHECK,
  2414. 0L,
  2415. 0L );
  2416. bChanged = ( !m_pChatCtl->m_bTimeStamp == !bVal ) ? bChanged : TRUE;
  2417. m_pChatCtl->m_bTimeStamp = (short)bVal;
  2418. bVal = (BOOL)::SendMessage( GetDlgItem(m_hOptionsDlg, IDC_INCLUDE_DATE ),
  2419. BM_GETCHECK,
  2420. 0L,
  2421. 0L );
  2422. bChanged = ( !m_pChatCtl->m_bUseDate == !bVal ) ? bChanged : TRUE;
  2423. m_pChatCtl->m_bUseDate = (short)bVal;
  2424. // Msg Style
  2425. CNmChatCtl::MSGSTYLE style;
  2426. if( ::SendMessage( GetDlgItem(m_hOptionsDlg, IDR_SINGLE_LINE ),
  2427. BM_GETCHECK,
  2428. 0L,
  2429. 0L ) )
  2430. {
  2431. style = CNmChatCtl::MSGSTYLE_NO_WRAP;
  2432. }
  2433. else if( ::SendMessage( GetDlgItem(m_hOptionsDlg, IDR_SAME_LINE ),
  2434. BM_GETCHECK,
  2435. 0L,
  2436. 0L ) )
  2437. {
  2438. style = CNmChatCtl::MSGSTYLE_1_LINE_WRAP;
  2439. }
  2440. else
  2441. {
  2442. style = CNmChatCtl::MSGSTYLE_2_LINE_WRAP;
  2443. }
  2444. bChanged = ( style == m_pChatCtl->get_MsgStyle() ) ? bChanged : TRUE;
  2445. // Fonts
  2446. for( int i = 0; i < FONT_COUNT; i++ )
  2447. {
  2448. if( m_bDirtyFonts[i] )
  2449. {
  2450. m_pChatCtl->m_hMsgColors[ i ] = m_hMsgColors[ i ];
  2451. m_pChatCtl->m_hMsgLogFonts[ i ] = m_hMsgLogFonts[ i ];
  2452. DeleteObject( m_pChatCtl->m_hMsgFonts[i] );
  2453. m_pChatCtl->m_hMsgFonts[i] = CreateFontIndirect( &m_pChatCtl->m_hMsgLogFonts[ i ] );
  2454. bChanged = TRUE;
  2455. }
  2456. }
  2457. if( bChanged )
  2458. {
  2459. m_pChatCtl->put_MsgStyle( style );
  2460. }
  2461. EndDialog(m_hOptionsDlg, IDOK );
  2462. return 0L;
  2463. }
  2464. LRESULT CChatOptionsDlg::OnCancelClicked()
  2465. {
  2466. EndDialog(m_hOptionsDlg, IDCANCEL );
  2467. return 0L;
  2468. }
  2469. LRESULT CChatOptionsDlg::OnFontClicked(WORD wID)
  2470. {
  2471. int iIndex = FONT_COUNT;
  2472. switch( wID )
  2473. {
  2474. case IDC_FONT_MSGOUT:
  2475. {
  2476. iIndex = FONT_MSGOUT;
  2477. break;
  2478. }
  2479. case IDC_FONT_MSGIN:
  2480. {
  2481. iIndex = FONT_MSGIN;
  2482. break;
  2483. }
  2484. case IDC_FONT_PRIVATEOUT:
  2485. {
  2486. iIndex = FONT_PRIVATEOUT;
  2487. break;
  2488. }
  2489. case IDC_FONT_PRIVATEIN:
  2490. {
  2491. iIndex = FONT_PRIVATEIN;
  2492. break;
  2493. }
  2494. default:
  2495. ASSERT( 0 );
  2496. }
  2497. CHOOSEFONT cf;
  2498. ZeroMemory( &cf, sizeof( cf ) );
  2499. cf.lStructSize = sizeof( cf );
  2500. cf.hwndOwner = m_hOptionsDlg;
  2501. cf.Flags = CF_FORCEFONTEXIST | CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT | CF_EFFECTS;
  2502. cf.lpLogFont = &m_hMsgLogFonts[ iIndex ];
  2503. cf.rgbColors = m_hMsgColors[ iIndex ];
  2504. if( ChooseFont( &cf ) )
  2505. {
  2506. m_bDirtyFonts[ iIndex ] = TRUE;
  2507. m_hMsgColors[ iIndex ] = cf.rgbColors;
  2508. _DisplayFontNameAndSize( iIndex );
  2509. }
  2510. return 0L;
  2511. }
  2512. //
  2513. //
  2514. // Function: _GetWindowRectOption
  2515. //
  2516. // Purpose: Retrieve a named option from the dictionary and convert it to
  2517. // a window rectangle. The rectangle is checked to make sure that
  2518. // it is at least partially on screen, and not zero sized.
  2519. //
  2520. //
  2521. void _GetWindowRectOption(LPRECT pRect)
  2522. {
  2523. RegEntry reWnd( CHAT_KEY, HKEY_CURRENT_USER );
  2524. pRect->left = reWnd.GetNumber( REGVAL_WINDOW_XPOS, 0);
  2525. pRect->top = reWnd.GetNumber( REGVAL_WINDOW_YPOS, 0);
  2526. int cx = reWnd.GetNumber( REGVAL_WINDOW_WIDTH, 0);
  2527. int cy = reWnd.GetNumber( REGVAL_WINDOW_HEIGHT, 0);
  2528. pRect->right = pRect->left + cx;
  2529. pRect->bottom = pRect->top + cy;
  2530. int iTop = pRect->top;
  2531. int iLeft = pRect->left;
  2532. int iBottom = pRect->bottom;
  2533. int iRight = pRect->right;
  2534. //
  2535. // If it was an empty rect
  2536. //
  2537. if( !(pRect->bottom || pRect->top || pRect->left || pRect->right) )
  2538. {
  2539. MINMAXINFO lpmmi;
  2540. g_pChatWindow->OnGetMinMaxInfo(&lpmmi);
  2541. iTop = 50;
  2542. iLeft = 50;
  2543. iBottom = lpmmi.ptMinTrackSize.y + 100;
  2544. iRight = lpmmi.ptMinTrackSize.x + 200;
  2545. pRect->top = iTop;
  2546. pRect->left = iLeft;
  2547. pRect->bottom = iBottom;
  2548. pRect->right = iRight;
  2549. return;
  2550. }
  2551. // Make sure that the window rectangle is (at least partially) on
  2552. // screen, and not too large. First get the screen size
  2553. int screenWidth = ::GetSystemMetrics(SM_CXSCREEN);
  2554. int screenHeight = ::GetSystemMetrics(SM_CYSCREEN);
  2555. // Check the window size
  2556. if ((iRight - iLeft) > screenWidth)
  2557. {
  2558. iRight = iLeft + screenWidth;
  2559. }
  2560. if ((iBottom - iTop) > screenHeight)
  2561. {
  2562. iTop = screenHeight;
  2563. }
  2564. // Check the window position
  2565. if (iLeft >= screenWidth)
  2566. {
  2567. // Off screen to the right - keep the width the same
  2568. iLeft = screenWidth - (iRight - iLeft);
  2569. iRight = screenWidth;
  2570. }
  2571. if (iRight < 0)
  2572. {
  2573. // Off screen to the left - keep the width the same
  2574. iRight = iRight - iLeft;
  2575. iLeft = 0;
  2576. }
  2577. if (iTop >= screenHeight)
  2578. {
  2579. // Off screen to the bottom - keep the height the same
  2580. iTop = screenHeight - (iBottom - iTop);
  2581. iBottom = screenHeight;
  2582. }
  2583. if (iBottom < 0)
  2584. {
  2585. // Off screen to the top - keep the height the same
  2586. iBottom = (iBottom - iTop);
  2587. iTop = 0;
  2588. }
  2589. pRect->left = iLeft;
  2590. pRect->top = iTop;
  2591. pRect->right = iRight;
  2592. pRect->bottom = iBottom;
  2593. }
  2594. //
  2595. //
  2596. // Function: SetWindowRectOption
  2597. //
  2598. // Purpose: Write a window position rectangle
  2599. //
  2600. //
  2601. void _SetWindowRectOption(LPCRECT pcRect)
  2602. {
  2603. RegEntry reWnd( CHAT_KEY, HKEY_CURRENT_USER );
  2604. reWnd.SetValue( REGVAL_WINDOW_XPOS, pcRect->left );
  2605. reWnd.SetValue( REGVAL_WINDOW_YPOS, pcRect->top );
  2606. reWnd.SetValue( REGVAL_WINDOW_WIDTH, pcRect->right - pcRect->left );
  2607. reWnd.SetValue( REGVAL_WINDOW_HEIGHT, pcRect->bottom - pcRect->top );
  2608. }