XListCtrlTestDlg.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. // XListCtrlTestDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "XListCtrlTest.h"
  5. #include "XListCtrlTestDlg.h"
  6. #include "about.h"
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12. ///////////////////////////////////////////////////////////////////////////////
  13. // CXListCtrlTestDlg dialog
  14. BEGIN_MESSAGE_MAP(CXListCtrlTestDlg, CDialog)
  15. //{{AFX_MSG_MAP(CXListCtrlTestDlg)
  16. ON_WM_SYSCOMMAND()
  17. ON_WM_PAINT()
  18. ON_WM_QUERYDRAGICON()
  19. ON_WM_TIMER()
  20. ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
  21. ON_WM_DESTROY()
  22. ON_NOTIFY(NM_CLICK, IDC_LIST, OnClick)
  23. ON_NOTIFY(NM_DBLCLK, IDC_LIST, OnDblClick)
  24. ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST, OnColumnClick)
  25. ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST, OnItemChanged)
  26. ON_BN_CLICKED(IDC_CLEAR, OnClear)
  27. ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
  28. ON_BN_CLICKED(IDC_CHECK1, OnGridlines)
  29. //}}AFX_MSG_MAP
  30. ON_REGISTERED_MESSAGE(WM_XLISTCTRL_COMBO_SELECTION, OnComboSelection)
  31. ON_REGISTERED_MESSAGE(WM_XLISTCTRL_CHECKBOX_CLICKED, OnCheckbox)
  32. ON_REGISTERED_MESSAGE(WM_XLISTCTRL_EDIT_END, OnEditEnd)
  33. END_MESSAGE_MAP()
  34. ///////////////////////////////////////////////////////////////////////////////
  35. // ctor
  36. CXListCtrlTestDlg::CXListCtrlTestDlg(CWnd* pParent /*=NULL*/)
  37. : CDialog(CXListCtrlTestDlg::IDD, pParent)
  38. {
  39. //{{AFX_DATA_INIT(CXListCtrlTestDlg)
  40. m_bGridlines = FALSE;
  41. //}}AFX_DATA_INIT
  42. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  43. m_bRunning = FALSE;
  44. m_bGridlines = TRUE;
  45. }
  46. ///////////////////////////////////////////////////////////////////////////////
  47. // DoDataExchange
  48. void CXListCtrlTestDlg::DoDataExchange(CDataExchange* pDX)
  49. {
  50. ///////////////////////////////////////////////////////////////////////////
  51. ///////////////////////////////////////////////////////////////////////////
  52. //
  53. // comment out the DDX_Control line to create CXListCtrl dynamically -
  54. // remember also to include lines in OnInitDialog to create CXListCtrl,
  55. // and remove the list control from IDD_LISTCTRLTEST_DIALOG in the rc file
  56. //
  57. ///////////////////////////////////////////////////////////////////////////
  58. ///////////////////////////////////////////////////////////////////////////
  59. CDialog::DoDataExchange(pDX);
  60. //{{AFX_DATA_MAP(CXListCtrlTestDlg)
  61. DDX_Control(pDX, IDC_LOG, m_Log);
  62. DDX_Control(pDX, IDC_LIST, m_List); // comment out this line if creating dynamically
  63. DDX_Check(pDX, IDC_CHECK1, m_bGridlines);
  64. //}}AFX_DATA_MAP
  65. }
  66. ///////////////////////////////////////////////////////////////////////////////
  67. // OnInitDialog
  68. BOOL CXListCtrlTestDlg::OnInitDialog()
  69. {
  70. TRACE(_T("in CXListCtrlTestDlg::OnInitDialog\n"));
  71. CDialog::OnInitDialog();
  72. // Add "About..." menu item to system menu.
  73. // IDM_ABOUTBOX must be in the system command range.
  74. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  75. ASSERT(IDM_ABOUTBOX < 0xF000);
  76. CMenu* pSysMenu = GetSystemMenu(FALSE);
  77. if (pSysMenu != NULL)
  78. {
  79. CString strAboutMenu;
  80. strAboutMenu.LoadString(IDS_ABOUTBOX);
  81. if (!strAboutMenu.IsEmpty())
  82. {
  83. pSysMenu->AppendMenu(MF_SEPARATOR);
  84. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  85. }
  86. }
  87. // Set the icon for this dialog. The framework does this automatically
  88. // when the application's main window is not a dialog
  89. SetIcon(m_hIcon, TRUE); // Set big icon
  90. SetIcon(m_hIcon, FALSE); // Set small icon
  91. ///////////////////////////////////////////////////////////////////////////
  92. ///////////////////////////////////////////////////////////////////////////
  93. //
  94. // include the following lines to create CXListCtrl dynamically -
  95. // remember also to comment out DDX line, and remove the list control
  96. // from IDD_LISTCTRLTEST_DIALOG in the rc file
  97. //
  98. ///////////////////////////////////////////////////////////////////////////
  99. ///////////////////////////////////////////////////////////////////////////
  100. #if 0 // -----------------------------------------------------------
  101. DWORD dwStyle = LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS |
  102. WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP;
  103. CRect rect, rectbutton;
  104. GetClientRect(&rect);
  105. GetDlgItem(IDC_BUTTON1)->GetClientRect(&rectbutton);
  106. rect.DeflateRect(5, 5);
  107. rect.top = rectbutton.bottom + 15;
  108. TRACE(" calling CreateEx\n");
  109. // you may also use Create(), but I prefer WS_EX_CLIENTEDGE style
  110. VERIFY(m_List.CreateEx(WS_EX_CLIENTEDGE, _T("SysListView32"), _T(""),
  111. dwStyle, rect, this, IDC_LIST, NULL));
  112. CFont *pFont = GetFont();
  113. if (pFont)
  114. m_List.SetFont(pFont);
  115. #endif // -----------------------------------------------------------
  116. // XListCtrl must have LVS_EX_FULLROWSELECT if combo or edit boxes are used
  117. DWORD dwExStyle = LVS_EX_FULLROWSELECT
  118. /*| LVS_EX_TRACKSELECT*/; // for hot tracking
  119. if (m_bGridlines)
  120. dwExStyle |= LVS_EX_GRIDLINES;
  121. m_List.SetExtendedStyle(dwExStyle);
  122. // call EnableToolTips to enable tooltip display
  123. m_List.EnableToolTips(TRUE);
  124. InitListCtrl(&m_List);
  125. return TRUE; // return TRUE unless you set the focus to a control
  126. }
  127. ///////////////////////////////////////////////////////////////////////////////
  128. // OnSysCommand
  129. void CXListCtrlTestDlg::OnSysCommand(UINT nID, LPARAM lParam)
  130. {
  131. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  132. {
  133. CAboutDlg dlg;
  134. dlg.DoModal();
  135. }
  136. else
  137. {
  138. CDialog::OnSysCommand(nID, lParam);
  139. }
  140. }
  141. ///////////////////////////////////////////////////////////////////////////////
  142. // OnPaint
  143. void CXListCtrlTestDlg::OnPaint()
  144. {
  145. if (IsIconic())
  146. {
  147. CPaintDC dc(this); // device context for painting
  148. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  149. // Center icon in client rectangle
  150. int cxIcon = GetSystemMetrics(SM_CXICON);
  151. int cyIcon = GetSystemMetrics(SM_CYICON);
  152. CRect rect;
  153. GetClientRect(&rect);
  154. int x = (rect.Width() - cxIcon + 1) / 2;
  155. int y = (rect.Height() - cyIcon + 1) / 2;
  156. // Draw the icon
  157. dc.DrawIcon(x, y, m_hIcon);
  158. }
  159. else
  160. {
  161. CDialog::OnPaint();
  162. }
  163. }
  164. ///////////////////////////////////////////////////////////////////////////////
  165. // OnQueryDragIcon
  166. HCURSOR CXListCtrlTestDlg::OnQueryDragIcon()
  167. {
  168. return (HCURSOR) m_hIcon;
  169. }
  170. ///////////////////////////////////////////////////////////////////////////////
  171. // OnTimer
  172. void CXListCtrlTestDlg::OnTimer(UINT nIDEvent)
  173. {
  174. static int nPct = 0;
  175. static int nItem = -1;
  176. static int nBlink = 0;
  177. if (nIDEvent == 1)
  178. {
  179. KillTimer(nIDEvent);
  180. m_List.SetProgress(1, 2);
  181. nPct = 0;
  182. SetTimer(2, 80, NULL);
  183. SetTimer(4, 400, NULL);
  184. }
  185. else if (nIDEvent == 2)
  186. {
  187. nPct += 10;
  188. m_List.UpdateProgress(1, 2, nPct);
  189. if (nPct >= 100)
  190. {
  191. KillTimer(nIDEvent);
  192. SetTimer(3, 2000, NULL);
  193. }
  194. }
  195. else if (nIDEvent == 3)
  196. {
  197. CString str;
  198. str = m_List.GetComboText(0, 2);
  199. KillTimer(nIDEvent);
  200. m_List.DeleteProgress(1, 2);
  201. SetTimer(1, 2000, NULL);
  202. }
  203. else if (nIDEvent == 4)
  204. {
  205. if (nItem != -1)
  206. {
  207. // remove previous color & bold from columns 1 and 5
  208. m_List.SetItemText(nItem, 5, NULL, (COLORREF)-1, (COLORREF)-1);
  209. m_List.SetBold(nItem, 1, FALSE);
  210. }
  211. // blink item 3
  212. if (nItem == 3)
  213. {
  214. nBlink++;
  215. if (nBlink >= 12)
  216. {
  217. nBlink = 0;
  218. nItem++;
  219. m_List.SetItemText(nItem, 5, NULL, RGB(255,255,255), RGB(255,0,0));
  220. m_List.SetBold(nItem, 1, TRUE);
  221. }
  222. else
  223. {
  224. if (nBlink & 1) // blink every other time
  225. {
  226. m_List.SetItemText(nItem, 5, NULL, RGB(255,255,255), RGB(255,0,0));
  227. m_List.SetBold(nItem, 1, TRUE);
  228. }
  229. }
  230. }
  231. else
  232. {
  233. nItem++;
  234. if (nItem >= 10)
  235. nItem = 0;
  236. m_List.SetItemText(nItem, 5, NULL, RGB(255,255,255), RGB(255,0,0));
  237. m_List.SetBold(nItem, 1, TRUE);
  238. }
  239. }
  240. CDialog::OnTimer(nIDEvent);
  241. }
  242. ///////////////////////////////////////////////////////////////////////////////
  243. // OnButton1
  244. void CXListCtrlTestDlg::OnButton1()
  245. {
  246. if (m_bRunning)
  247. {
  248. GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
  249. KillTimer(1);
  250. KillTimer(2);
  251. KillTimer(3);
  252. KillTimer(4);
  253. m_bRunning = FALSE;
  254. GetDlgItem(IDC_BUTTON1)->SetWindowText(_T("Start"));
  255. GetDlgItem(IDC_BUTTON1)->EnableWindow(TRUE);
  256. }
  257. else
  258. {
  259. GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
  260. FillListCtrl(&m_List);
  261. // show a disabled item
  262. m_List.SetEnabled(5, FALSE);
  263. m_List.SetItemText(5, 1, _T("This row is disabled"));
  264. #if 0 // -----------------------------------------------------------
  265. // demonstrate handling of WM_SYSCOLORCHANGE
  266. int nElement = COLOR_WINDOW;
  267. COLORREF crWindow = ::GetSysColor(nElement);
  268. if (::SetSysColors(1, // number of elements
  269. &nElement, // array of elements
  270. &crWindow)) // array of RGB values
  271. {
  272. TRACE(_T("SetSysColors ok\n"));
  273. }
  274. else
  275. {
  276. TRACE(_T("SetSysColors failed\n"));
  277. }
  278. #endif // -----------------------------------------------------------
  279. SetTimer(1, 1000, NULL);
  280. m_bRunning = TRUE;
  281. GetDlgItem(IDC_BUTTON1)->SetWindowText(_T("Stop"));
  282. GetDlgItem(IDC_BUTTON1)->EnableWindow(TRUE);
  283. }
  284. }
  285. ///////////////////////////////////////////////////////////////////////////////
  286. // OnButton2 - mark all subitems as unmodified
  287. void CXListCtrlTestDlg::OnButton2()
  288. {
  289. m_List.SetListModified(FALSE);
  290. for (int nItem = 0; nItem < m_List.GetItemCount(); nItem++)
  291. {
  292. for (int nSubItem = 0; nSubItem < m_List.GetColumns(); nSubItem++)
  293. {
  294. m_List.SetModified(nItem, nSubItem, FALSE);
  295. COLORREF crText, crBackground;
  296. m_List.GetItemColors(nItem, nSubItem, crText, crBackground);
  297. m_List.SetItemColors(nItem, nSubItem, RGB(0,0,0), crBackground);
  298. // is this a checkbox?
  299. if (m_List.GetItemCheckedState(nItem, nSubItem) != -1)
  300. {
  301. if (nSubItem == 0)
  302. m_List.SetItemText(nItem, nSubItem, _T(" ")); // erase *
  303. else
  304. m_List.SetItemText(nItem, nSubItem, _T("OK"));
  305. }
  306. }
  307. }
  308. m_List.RedrawWindow();
  309. CString strCaption = _T("");
  310. strCaption.LoadString(AFX_IDS_APP_TITLE);
  311. SetWindowText(strCaption);
  312. }
  313. ///////////////////////////////////////////////////////////////////////////////
  314. // OnClear - clear m_Log listbox
  315. void CXListCtrlTestDlg::OnClear()
  316. {
  317. m_Log.ResetContent();
  318. }
  319. ///////////////////////////////////////////////////////////////////////////////
  320. // OnGridlines
  321. void CXListCtrlTestDlg::OnGridlines()
  322. {
  323. UpdateData(TRUE);
  324. DWORD dwExStyle = m_List.GetExtendedStyle();
  325. if (m_bGridlines)
  326. dwExStyle |= LVS_EX_GRIDLINES;
  327. else
  328. dwExStyle &= ~LVS_EX_GRIDLINES;
  329. m_List.SetExtendedStyle(dwExStyle);
  330. }
  331. ///////////////////////////////////////////////////////////////////////////////
  332. // OnDestroy
  333. void CXListCtrlTestDlg::OnDestroy()
  334. {
  335. KillTimer(1);
  336. KillTimer(2);
  337. KillTimer(3);
  338. KillTimer(4);
  339. CDialog::OnDestroy();
  340. }
  341. ///////////////////////////////////////////////////////////////////////////////
  342. // OnClick
  343. //
  344. // This method shows how to handle NM_CLICK messages from XListCtrl
  345. //
  346. void CXListCtrlTestDlg::OnClick(NMHDR* pNMHDR, LRESULT* pResult)
  347. {
  348. LPNMITEMACTIVATE pNMIA = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
  349. int nItem = -1;
  350. int nSubItem = -1;
  351. if (pNMIA)
  352. {
  353. nItem = pNMIA->iItem;
  354. nSubItem = pNMIA->iSubItem;
  355. }
  356. if (nItem >= 0 && nSubItem >= 0)
  357. {
  358. CString strText = m_List.GetItemText(nItem, nSubItem);
  359. Log(_T("OnClick at (%d,%d): '%s'"), nItem, nSubItem, strText);
  360. }
  361. *pResult = 0;
  362. }
  363. ///////////////////////////////////////////////////////////////////////////////
  364. // OnDblClick
  365. //
  366. // This method shows how to handle NM_DBLCLK messages from XListCtrl
  367. //
  368. void CXListCtrlTestDlg::OnDblClick(NMHDR* pNMHDR, LRESULT* pResult)
  369. {
  370. LPNMITEMACTIVATE pNMIA = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
  371. int nItem = -1;
  372. int nSubItem = -1;
  373. if (pNMIA)
  374. {
  375. nItem = pNMIA->iItem;
  376. nSubItem = pNMIA->iSubItem;
  377. }
  378. if (nItem >= 0 && nSubItem >= 0)
  379. {
  380. CString strText = m_List.GetItemText(nItem, nSubItem);
  381. Log(_T("OnDblClick at (%d,%d): '%s'"), nItem, nSubItem, strText);
  382. }
  383. *pResult = 0;
  384. }
  385. ///////////////////////////////////////////////////////////////////////////////
  386. // OnColumnClick
  387. //
  388. // This method shows how to handle LVN_COLUMNCLICK messages from XListCtrl
  389. //
  390. void CXListCtrlTestDlg::OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult)
  391. {
  392. LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
  393. int nItem = -1;
  394. int nSubItem = -1;
  395. if (pNMLV)
  396. {
  397. nItem = pNMLV->iItem;
  398. nSubItem = pNMLV->iSubItem;
  399. }
  400. Log(_T("OnColumnClick on column %d"), nSubItem);
  401. CString strCaption = _T("");
  402. strCaption.LoadString(AFX_IDS_APP_TITLE);
  403. strCaption += _T(" *");
  404. SetWindowText(strCaption);
  405. *pResult = 0;
  406. }
  407. ///////////////////////////////////////////////////////////////////////////////
  408. // OnItemChanged
  409. //
  410. // This method shows how to handle LVN_ITEMCHANGED messages from XListCtrl
  411. //
  412. void CXListCtrlTestDlg::OnItemChanged(NMHDR* pNMHDR, LRESULT* pResult)
  413. {
  414. LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
  415. int nItem = -1;
  416. int nSubItem = -1;
  417. if (pNMLV)
  418. {
  419. nItem = pNMLV->iItem;
  420. nSubItem = pNMLV->iSubItem;
  421. }
  422. //TRACE(_T("in CXListCtrlTestDlg::OnItemChanged: %d, %d\n"), nItem, nSubItem);
  423. if (pNMLV && (pNMLV->uNewState == (UINT)(LVIS_FOCUSED|LVIS_SELECTED)))
  424. {
  425. CString strText = m_List.GetItemText(nItem, nSubItem);
  426. Log(_T("Selection changed to item %d"), nItem);
  427. }
  428. *pResult = 0;
  429. }
  430. ///////////////////////////////////////////////////////////////////////////////
  431. // OnEditEnd
  432. //
  433. // This method shows how to handle WM_XLISTCTRL_EDIT_END messages
  434. // from XListCtrl
  435. //
  436. LRESULT CXListCtrlTestDlg::OnEditEnd(WPARAM nItem, LPARAM nSubItem)
  437. {
  438. if (nItem >= 0 && nSubItem >= 0)
  439. {
  440. CString strText = m_List.GetItemText(nItem, nSubItem);
  441. Log(_T("OnEditEnd at (%d,%d): '%s'"), nItem, nSubItem, strText);
  442. COLORREF crText, crBackground;
  443. m_List.GetItemColors(nItem, nSubItem, crText, crBackground);
  444. if (m_List.GetModified(nItem, nSubItem))
  445. {
  446. // subitem was modified - color it red
  447. m_List.SetItemText(nItem, nSubItem, strText,
  448. RGB(255,0,0), crBackground);
  449. CString strCaption = _T("");
  450. strCaption.LoadString(AFX_IDS_APP_TITLE);
  451. strCaption += _T(" *");
  452. SetWindowText(strCaption);
  453. }
  454. else
  455. {
  456. // subitem not modified - color it black -
  457. // note that once modified, a subitem will remain
  458. // marked as modified
  459. m_List.SetItemText(nItem, nSubItem, strText,
  460. RGB(0,0,0), crBackground);
  461. }
  462. }
  463. return 0;
  464. }
  465. ///////////////////////////////////////////////////////////////////////////////
  466. // OnComboSelection
  467. //
  468. // This method shows how to handle WM_XLISTCTRL_COMBO_SELECTION messages
  469. // from XListCtrl
  470. //
  471. LRESULT CXListCtrlTestDlg::OnComboSelection(WPARAM nItem, LPARAM nSubItem)
  472. {
  473. if (nItem >= 0 && nSubItem >= 0)
  474. {
  475. CString strText = m_List.GetItemText(nItem, nSubItem);
  476. Log(_T("OnComboSelection at (%d,%d): '%s'"), nItem, nSubItem, strText);
  477. COLORREF crText, crBackground;
  478. m_List.GetItemColors(nItem, nSubItem, crText, crBackground);
  479. if (m_List.GetModified(nItem, nSubItem))
  480. {
  481. // subitem was modified - color it red
  482. m_List.SetItemText(nItem, nSubItem, strText,
  483. RGB(255,0,0), crBackground);
  484. CString strCaption = _T("");
  485. strCaption.LoadString(AFX_IDS_APP_TITLE);
  486. strCaption += _T(" *");
  487. SetWindowText(strCaption);
  488. }
  489. else
  490. {
  491. // subitem not modified - color it black -
  492. // note that once modified, a subitem will remain
  493. // marked as modified
  494. m_List.SetItemText(nItem, nSubItem, strText,
  495. RGB(0,0,0), crBackground);
  496. }
  497. }
  498. return 0;
  499. }
  500. ///////////////////////////////////////////////////////////////////////////////
  501. // OnCheckbox
  502. //
  503. // This method shows how to handle WM_XLISTCTRL_CHECKBOX_CLICKED messages
  504. // from XListCtrl
  505. //
  506. LRESULT CXListCtrlTestDlg::OnCheckbox(WPARAM nItem, LPARAM nSubItem)
  507. {
  508. if (nItem >= 0 && nSubItem >= 0)
  509. {
  510. Log(_T("OnCheckbox at (%d,%d)"), nItem, nSubItem);
  511. COLORREF crText, crBackground;
  512. m_List.GetItemColors(nItem, nSubItem, crText, crBackground);
  513. if (m_List.GetModified(nItem, nSubItem))
  514. {
  515. // subitem was modified - color it red
  516. if (nSubItem == 0)
  517. m_List.SetItemText(nItem, nSubItem, _T("*"),
  518. RGB(255,0,0), crBackground);
  519. else
  520. m_List.SetItemText(nItem, nSubItem, _T("Error"),
  521. RGB(255,0,0), crBackground);
  522. CString strCaption = _T("");
  523. strCaption.LoadString(AFX_IDS_APP_TITLE);
  524. strCaption += _T(" *");
  525. SetWindowText(strCaption);
  526. }
  527. else
  528. {
  529. // subitem not modified - color it black -
  530. // note that once modified, a subitem will remain
  531. // marked as modified
  532. if (nSubItem == 0)
  533. m_List.SetItemText(nItem, nSubItem, _T(" "),
  534. RGB(0,0,0), crBackground);
  535. else
  536. m_List.SetItemText(nItem, nSubItem, _T("OK"),
  537. RGB(255,0,0), crBackground);
  538. }
  539. }
  540. return 0;
  541. }
  542. ///////////////////////////////////////////////////////////////////////////////
  543. // Log - log a message to the m_Log listbox
  544. void _cdecl CXListCtrlTestDlg::Log(LPCTSTR lpszFmt, ...)
  545. {
  546. ASSERT(lpszFmt);
  547. TCHAR buf[2000], fmt[2000];
  548. va_list marker;
  549. // format string was passed as parameter
  550. _tcsncpy(fmt, lpszFmt, sizeof(fmt)/sizeof(TCHAR)-1);
  551. fmt[sizeof(fmt)/sizeof(TCHAR)-1] = _T('\0');
  552. // combine output string and variables
  553. va_start(marker, lpszFmt);
  554. _vsntprintf(buf, (sizeof(buf)/sizeof(TCHAR))-1, fmt, marker);
  555. va_end(marker);
  556. buf[sizeof(buf)/sizeof(TCHAR)-1] = _T('\0');
  557. CString strMsg(buf);
  558. // don't display \r or \n characters
  559. int i = 0;
  560. while ((i = strMsg.FindOneOf(_T("\r\n"))) != -1)
  561. strMsg.SetAt(i, _T(' '));
  562. i = m_Log.AddString(strMsg);
  563. TRACE(_T("%s\n"), strMsg);
  564. // scroll into view
  565. if (i >= 0)
  566. {
  567. m_Log.SetTopIndex(i);
  568. }
  569. m_Log.SetCurSel(-1);
  570. }