Leaked source code of windows server 2003
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.

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