QListCtrlCtl.cpp
上传用户:cnjubao
上传日期:2007-01-02
资源大小:34k
文件大小:32k
源码类别:

ListView/ListBox

开发平台:

Visual C++

  1. /************************************
  2.   REVISION LOG ENTRY
  3.   Revision By: Mihai Filimon
  4.   Revised on 11/2/98 3:29:27 PM
  5.   Comments: QListCtrlCtl.cpp : Implementation of the CQListCtrlCtrl ActiveX Control class.
  6.  ************************************/
  7. #include "stdafx.h"
  8. #include "QListCtrl.h"
  9. #include "QListCtrlCtl.h"
  10. #include "QListCtrlPpg.h"
  11. #ifdef _DEBUG
  12. #define new DEBUG_NEW
  13. #undef THIS_FILE
  14. static char THIS_FILE[] = __FILE__;
  15. #endif
  16. IMPLEMENT_DYNCREATE(CQListCtrlCtrl, COleControl)
  17. /////////////////////////////////////////////////////////////////////////////
  18. // Message map
  19. BEGIN_MESSAGE_MAP(CQListCtrlCtrl, COleControl)
  20. //{{AFX_MSG_MAP(CQListCtrlCtrl)
  21. ON_WM_CREATE()
  22. ON_WM_DRAWITEM_REFLECT()
  23. ON_WM_MEASUREITEM_REFLECT()
  24. ON_WM_SIZE()
  25. ON_WM_DESTROY()
  26. ON_WM_NCCALCSIZE()
  27. ON_WM_SHOWWINDOW()
  28. ON_WM_VSCROLL()
  29. ON_WM_KEYDOWN()
  30. //}}AFX_MSG_MAP
  31. ON_MESSAGE(OCM_COMMAND, OnOcmCommand)
  32. ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
  33. END_MESSAGE_MAP()
  34. /////////////////////////////////////////////////////////////////////////////
  35. // Dispatch map
  36. BEGIN_DISPATCH_MAP(CQListCtrlCtrl, COleControl)
  37. //{{AFX_DISPATCH_MAP(CQListCtrlCtrl)
  38. DISP_PROPERTY_NOTIFY(CQListCtrlCtrl, "ItemHeight", m_nItemHeight, OnItemHeightChanged, VT_I4)
  39. DISP_PROPERTY_NOTIFY(CQListCtrlCtrl, "GridLines", m_bGridLines, OnGridLinesChanged, VT_BOOL)
  40. DISP_PROPERTY_NOTIFY(CQListCtrlCtrl, "Header", m_sHeader, OnHeaderChanged, VT_BSTR)
  41. DISP_PROPERTY_NOTIFY(CQListCtrlCtrl, "MultiSelect", m_bMultiSelect, OnMultiSelectChanged, VT_BOOL)
  42. DISP_PROPERTY_NOTIFY(CQListCtrlCtrl, "NoHeader", m_bNoHeader, OnNoHeaderChanged, VT_BOOL)
  43. DISP_PROPERTY_NOTIFY(CQListCtrlCtrl, "SColumn", m_bSColumn, OnSColumnChanged, VT_BOOL)
  44. DISP_FUNCTION(CQListCtrlCtrl, "InitItemsCount", InitItemsCount, VT_EMPTY, VTS_NONE)
  45. DISP_STOCKPROP_FONT()
  46. //}}AFX_DISPATCH_MAP
  47. DISP_FUNCTION_ID(CQListCtrlCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
  48. END_DISPATCH_MAP()
  49. /////////////////////////////////////////////////////////////////////////////
  50. // Event map
  51. BEGIN_EVENT_MAP(CQListCtrlCtrl, COleControl)
  52. //{{AFX_EVENT_MAP(CQListCtrlCtrl)
  53. EVENT_CUSTOM("ItemsCount", FireItemsCount, VTS_PI4)
  54. EVENT_CUSTOM("AllItemsLoaded", FireAllItemsLoaded, VTS_NONE)
  55. EVENT_CUSTOM("LoadLabel", FireLoadLabel, VTS_I4  VTS_PBSTR  VTS_PI4)
  56. EVENT_CUSTOM("LoadSubItem", FireLoadSubItem, VTS_I4  VTS_I4  VTS_PBSTR)
  57. //}}AFX_EVENT_MAP
  58. END_EVENT_MAP()
  59. /////////////////////////////////////////////////////////////////////////////
  60. // Property pages
  61. // TODO: Add more property pages as needed.  Remember to increase the count!
  62. BEGIN_PROPPAGEIDS(CQListCtrlCtrl, 2)
  63. PROPPAGEID(CQListCtrlPropPage::guid)
  64. PROPPAGEID(CLSID_CFontPropPage )
  65. END_PROPPAGEIDS(CQListCtrlCtrl)
  66. /////////////////////////////////////////////////////////////////////////////
  67. // Initialize class factory and guid
  68. IMPLEMENT_OLECREATE_EX(CQListCtrlCtrl, "QLISTCTRL.QListCtrlCtrl.1",
  69. 0xbfcc1bc6, 0x7257, 0x11d2, 0x86, 0xe6, 0, 0x40, 0x5, 0x5c, 0x8, 0xd9)
  70. /////////////////////////////////////////////////////////////////////////////
  71. // Type library ID and version
  72. IMPLEMENT_OLETYPELIB(CQListCtrlCtrl, _tlid, _wVerMajor, _wVerMinor)
  73. /////////////////////////////////////////////////////////////////////////////
  74. // Interface IDs
  75. const IID BASED_CODE IID_DQListCtrl =
  76. { 0xbfcc1bc4, 0x7257, 0x11d2, { 0x86, 0xe6, 0, 0x40, 0x5, 0x5c, 0x8, 0xd9 } };
  77. const IID BASED_CODE IID_DQListCtrlEvents =
  78. { 0xbfcc1bc5, 0x7257, 0x11d2, { 0x86, 0xe6, 0, 0x40, 0x5, 0x5c, 0x8, 0xd9 } };
  79. /////////////////////////////////////////////////////////////////////////////
  80. // Control type information
  81. static const DWORD BASED_CODE _dwQListCtrlOleMisc =
  82. OLEMISC_ACTIVATEWHENVISIBLE |
  83. OLEMISC_SETCLIENTSITEFIRST |
  84. OLEMISC_INSIDEOUT |
  85. OLEMISC_CANTLINKINSIDE |
  86. OLEMISC_RECOMPOSEONRESIZE;
  87. IMPLEMENT_OLECTLTYPE(CQListCtrlCtrl, IDS_QLISTCTRL, _dwQListCtrlOleMisc)
  88. /////////////////////////////////////////////////////////////////////////////
  89. // CQListCtrlCtrl::CQListCtrlCtrlFactory::UpdateRegistry -
  90. // Adds or removes system registry entries for CQListCtrlCtrl
  91. // Function name : CQListCtrlCtrl::CQListCtrlCtrlFactory::UpdateRegistry
  92. // Description     : Update the registry
  93. // Return type : BOOL 
  94. // Argument         : BOOL bRegister
  95. BOOL CQListCtrlCtrl::CQListCtrlCtrlFactory::UpdateRegistry(BOOL bRegister)
  96. {
  97. // TODO: Verify that your control follows apartment-model threading rules.
  98. // Refer to MFC TechNote 64 for more information.
  99. // If your control does not conform to the apartment-model rules, then
  100. // you must modify the code below, changing the 6th parameter from
  101. // afxRegApartmentThreading to 0.
  102. if (bRegister)
  103. return AfxOleRegisterControlClass(
  104. AfxGetInstanceHandle(),
  105. m_clsid,
  106. m_lpszProgID,
  107. IDS_QLISTCTRL,
  108. IDB_QLISTCTRL,
  109. afxRegApartmentThreading,
  110. _dwQListCtrlOleMisc,
  111. _tlid,
  112. _wVerMajor,
  113. _wVerMinor);
  114. else
  115. return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
  116. }
  117. /////////////////////////////////////////////////////////////////////////////
  118. // Licensing strings
  119. static const TCHAR BASED_CODE _szLicFileName[] = _T("QListCtrl.lic");
  120. static const WCHAR BASED_CODE _szLicString[] =
  121. L"Copyright (c) 1998 Filimon";
  122. /////////////////////////////////////////////////////////////////////////////
  123. // CQListCtrlCtrl::CQListCtrlCtrlFactory::VerifyUserLicense -
  124. // Checks for existence of a user license
  125. // Function name : CQListCtrlCtrl::CQListCtrlCtrlFactory::VerifyUserLicense
  126. // Description     : Verify license
  127. // Return type : BOOL 
  128. BOOL CQListCtrlCtrl::CQListCtrlCtrlFactory::VerifyUserLicense()
  129. {
  130. return AfxVerifyLicFile(AfxGetInstanceHandle(), _szLicFileName,
  131. _szLicString);
  132. }
  133. /////////////////////////////////////////////////////////////////////////////
  134. // CQListCtrlCtrl::CQListCtrlCtrlFactory::GetLicenseKey -
  135. // Returns a runtime licensing key
  136. BOOL CQListCtrlCtrl::CQListCtrlCtrlFactory::GetLicenseKey(DWORD dwReserved,
  137. BSTR FAR* pbstrKey)
  138. {
  139. if (pbstrKey == NULL)
  140. return FALSE;
  141. *pbstrKey = SysAllocString(_szLicString);
  142. return (*pbstrKey != NULL);
  143. }
  144. /////////////////////////////////////////////////////////////////////////////
  145. // CQListCtrlCtrl::CQListCtrlCtrl - Constructor
  146. // Function name : CQListCtrlCtrl::CQListCtrlCtrl
  147. // Description     : Default constructor
  148. // Return type : 
  149. CQListCtrlCtrl::CQListCtrlCtrl()
  150. {
  151. InitializeIIDs(&IID_DQListCtrl, &IID_DQListCtrlEvents);
  152. m_nItemsCount = -1;
  153. m_nCountLoading  = 0;
  154. m_QuickLoader.SetParent(this);
  155. m_fctLoadFunction = NULL;
  156. }
  157. /////////////////////////////////////////////////////////////////////////////
  158. // CQListCtrlCtrl::~CQListCtrlCtrl - Destructor
  159. // Function name : CQListCtrlCtrl::~CQListCtrlCtrl
  160. // Description     : 
  161. // Return type : 
  162. CQListCtrlCtrl::~CQListCtrlCtrl()
  163. {
  164. // TODO: Cleanup your control's instance data here.
  165. }
  166. // Function name : CQListCtrlCtrl::GetListCtrl
  167. // Description     : 
  168. // Return type : CListCtrl* 
  169. CListCtrl* CQListCtrlCtrl::GetListCtrl()
  170. {
  171. return (CListCtrl*)this;
  172. }
  173. /////////////////////////////////////////////////////////////////////////////
  174. // CQListCtrlCtrl::OnDraw - Drawing function
  175. void CQListCtrlCtrl::OnDraw(
  176. CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
  177. {
  178. if (m_hWnd != NULL)
  179. {
  180. CRect rcClient;
  181. GetClientRect(&rcClient);
  182. if (rcClient.Size() != rcBounds.Size())
  183. {
  184. pdc->SetMapMode(MM_ANISOTROPIC);
  185. pdc->SetWindowExt(rcClient.right, rcClient.bottom);
  186. pdc->SetViewportExt(rcBounds.Size());
  187. }
  188. pdc->SetWindowOrg(0, 0);
  189. pdc->SetViewportOrg(rcBounds.left, rcBounds.top);
  190. ::CallWindowProc(*GetSuperWndProcAddr(), m_hWnd, WM_PRINT, (WPARAM)(pdc->m_hDC), (LPARAM)(PRF_ERASEBKGND | PRF_CLIENT | PRF_CHILDREN | PRF_NONCLIENT));
  191. }
  192. else
  193. {
  194. CFont* pFont = SelectStockFont(pdc);
  195. CString text;
  196. text.Format(_T("QListCtrl %i.%i Control"), _wVerMajor, _wVerMinor);
  197. pdc->DrawText(text, CRect(rcInvalid), DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  198. pdc->SelectObject(pFont);
  199. }
  200. return;
  201. }
  202. /////////////////////////////////////////////////////////////////////////////
  203. // CQListCtrlCtrl::DoPropExchange - Persistence support
  204. // Function name : CQListCtrlCtrl::DoPropExchange
  205. // Description     : Save/Load the properties
  206. // Return type : void 
  207. // Argument         : CPropExchange* pPX
  208. void CQListCtrlCtrl::DoPropExchange(CPropExchange* pPX)
  209. {
  210. ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
  211. COleControl::DoPropExchange(pPX);
  212. PX_Long(pPX, _T("ItemHeight"), m_nItemHeight, defaultItemHeight);
  213. PX_Bool(pPX, _T("GridLines"), m_bGridLines, TRUE);
  214. PX_Bool(pPX, _T("MultiSelect"), m_bMultiSelect, TRUE);
  215. PX_String(pPX, _T("Header"), m_sHeader, _T(""));
  216. PX_Bool(pPX, _T("NoHeader"), m_bNoHeader, FALSE);
  217. PX_Bool(pPX, _T("SColumn"), m_bSColumn, FALSE);
  218. }
  219. /////////////////////////////////////////////////////////////////////////////
  220. // CQListCtrlCtrl::OnResetState - Reset control to default state
  221. // Function name : CQListCtrlCtrl::OnResetState
  222. // Description     : On default value
  223. // Return type : void 
  224. void CQListCtrlCtrl::OnResetState()
  225. {
  226. COleControl::OnResetState();  // Resets defaults found in DoPropExchange
  227. }
  228. /////////////////////////////////////////////////////////////////////////////
  229. // CQListCtrlCtrl::AboutBox - Display an "About" box to the user
  230. // Function name : CQListCtrlCtrl::AboutBox
  231. // Description     : do an about box
  232. // Return type : void 
  233. void CQListCtrlCtrl::AboutBox()
  234. {
  235. CDialog dlgAbout(IDD_ABOUTBOX_QLISTCTRL);
  236. // dlgAbout.DoModal();
  237. LV_COLUMN lColumn; lColumn.mask = LVCF_FMT;
  238. for (int j = 0; j < 32; j++)
  239. {
  240. int nItem = GetListCtrl()->InsertItem(0, RandomString());
  241. for (int i = 1; GetListCtrl()->GetColumn(i, &lColumn); i++)
  242. GetListCtrl()->SetItemText(nItem, i, RandomString());
  243. }
  244. }
  245. /////////////////////////////////////////////////////////////////////////////
  246. // CQListCtrlCtrl::PreCreateWindow - Modify parameters for CreateWindowEx
  247. // Function name : CQListCtrlCtrl::PreCreateWindow
  248. // Description     : Create OLEControl as SysListView32
  249. // Return type : BOOL 
  250. // Argument         : CREATESTRUCT& cs
  251. BOOL CQListCtrlCtrl::PreCreateWindow(CREATESTRUCT& cs)
  252. {
  253. cs.lpszClass = _T("SysListView32");
  254. cs.style |= defaultStyles | (m_bSColumn ? LVS_NOSORTHEADER : 0);
  255. return COleControl::PreCreateWindow(cs);
  256. }
  257. /////////////////////////////////////////////////////////////////////////////
  258. // CQListCtrlCtrl::IsSubclassedControl - This is a subclassed control
  259. // Function name : CQListCtrlCtrl::IsSubclassedControl
  260. // Description     : 
  261. // Return type : BOOL 
  262. BOOL CQListCtrlCtrl::IsSubclassedControl()
  263. {
  264. return TRUE;
  265. }
  266. /////////////////////////////////////////////////////////////////////////////
  267. // CQListCtrlCtrl::OnOcmCommand - Handle command messages
  268. LRESULT CQListCtrlCtrl::OnOcmCommand(WPARAM wParam, LPARAM lParam)
  269. {
  270. #ifdef _WIN32
  271. WORD wNotifyCode = HIWORD(wParam);
  272. #else
  273. WORD wNotifyCode = HIWORD(lParam);
  274. #endif
  275. return 0;
  276. }
  277. /////////////////////////////////////////////////////////////////////////////
  278. // CQListCtrlCtrl message handlers
  279. // Function name : CQListCtrlCtrl::OnInit
  280. // Description     : 
  281. // Return type : void 
  282. void CQListCtrlCtrl::OnInit()
  283. {
  284. OnGridLinesChanged();
  285. OnHeaderChanged();
  286. OnMultiSelectChanged();
  287. OnNoHeaderChanged();
  288. OnSColumnChanged();
  289. }
  290. // Function name : CQListCtrlCtrl::OnDestroy
  291. // Description     : On destroy we will uninstall hook procedure
  292. // Return type : void 
  293. void CQListCtrlCtrl::OnDestroy() 
  294. {
  295. COleControl::OnDestroy();
  296. }
  297. // Function name : CQListCtrlCtrl::OnCreate
  298. // Description     : Call to set opr not the grid lines of control
  299. // Return type : int 
  300. // Argument         : LPCREATESTRUCT lpCreateStruct
  301. int CQListCtrlCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  302. {
  303. if (COleControl::OnCreate(lpCreateStruct) == -1)
  304. return -1;
  305. ASSERT (GetStyle() & (LVS_REPORT | LVS_OWNERDRAWFIXED) );
  306. OnInit();
  307. return 0;
  308. }
  309. // Function name : CQListCtrlCtrl::MeasureItem
  310. // Description     : Measure the item
  311. // Return type : void 
  312. // Argument         : LPMEASUREITEMSTRUCT lpMeasureItemStruct
  313. void CQListCtrlCtrl::MeasureItem( LPMEASUREITEMSTRUCT lpMeasureItemStruct ) 
  314. {
  315. lpMeasureItemStruct->itemHeight = m_nItemHeight;
  316. }
  317. // Function name : CQListCtrlCtrl::FormatColumn
  318. // Description     : Return the draw format for iColumn
  319. // Return type : UINT 
  320. // Argument         : int iColumn
  321. UINT CQListCtrlCtrl::FormatColumn(int iColumn)
  322. {
  323. LV_COLUMN lColumn; lColumn.mask = LVCF_FMT;
  324. if (GetListCtrl()->GetColumn(iColumn, &lColumn))
  325. return lColumn.fmt & LVCFMT_JUSTIFYMASK;
  326. return 0;
  327. }
  328. #define formatDrawText DT_VCENTER | DT_SINGLELINE
  329. // Function name : CQListCtrlCtrl::DrawItem
  330. // Description     : Drawing an item
  331. // Return type : void 
  332. // Argument         : LPDRAWITEMSTRUCT lpDrawItemStruct
  333. void CQListCtrlCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
  334. {
  335. CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  336. CListCtrl* pListCtrl = GetListCtrl();
  337. CRect rectDraw(lpDrawItemStruct->rcItem);
  338. CRect rectItem(rectDraw);
  339. int nItem = lpDrawItemStruct->itemID;
  340. CRect rectAll; pListCtrl->GetItemRect(nItem, rectAll, LVIR_BOUNDS);
  341. CRect rectLabel; pListCtrl->GetItemRect(nItem, rectLabel, LVIR_LABEL);
  342. BOOL bFocused = GetFocus() && (pListCtrl->GetItemState(nItem, LVIS_FOCUSED) == LVIS_FOCUSED);
  343. BOOL bSelected = pListCtrl->GetItemState(nItem, LVIS_SELECTED) == LVIS_SELECTED;
  344. LV_COLUMN lColumn; lColumn.mask = LVCF_WIDTH;
  345. rectItem.left += 2;
  346. pDC->SetTextColor(bSelected & bFocused ? RGB(255,255,255) : RGB(0,0,0));
  347. CBrush brush(bSelected ? (bFocused ? RGB(0,0,128) : RGB(192,192,192)) : RGB(255,255,255));
  348. pDC->FillRect(rectAll, &brush);
  349. // Select the item font
  350. CFont* pFont = SelectStockFont(pDC);
  351. for (int i = 0; pListCtrl->GetColumn(i, &lColumn); i++, rectItem.left += lColumn.cx + 2)
  352. {
  353. rectItem.right = rectItem.left + lColumn.cx - 2;
  354. pDC->DrawText(pListCtrl->GetItemText(nItem, i), rectItem, formatDrawText | FormatColumn(i));
  355. }
  356. pDC->SelectObject(pFont);
  357. pDC->SetTextColor(RGB(0,0,0));
  358. // Deselect the item font
  359. if (bFocused)
  360. {
  361. rectAll.InflateRect(0,-2);
  362. rectAll.bottom++;
  363. pDC->FrameRect(rectAll, &CBrush(RGB(0,0,0)));
  364. }
  365. }
  366. // Function name : CQListCtrlCtrl::OnItemHeightChanged
  367. // Description     : Set the item height
  368. // Return type : void 
  369. void CQListCtrlCtrl::OnItemHeightChanged() 
  370. {
  371. m_nItemHeight = abs(m_nItemHeight);
  372. m_nItemHeight = max(1,m_nItemHeight);
  373. ASSERT (m_nItemHeight > 0);
  374. SetModifiedFlag();
  375. }
  376. // Function name : CQListCtrlCtrl::OnGridLinesChanged
  377. // Description     : Set or not the grid lines
  378. // Return type : void 
  379. void CQListCtrlCtrl::OnGridLinesChanged() 
  380. {
  381. if (::IsWindow(GetSafeHwnd()))
  382. ListView_SetExtendedListViewStyle(m_hWnd, (m_bGridLines ? LVS_EX_GRIDLINES : 0) | LVS_EX_FULLROWSELECT );
  383. SetModifiedFlag();
  384. }
  385. // Function name : CQListCtrlCtrl::OnHeaderChanged
  386. // Description     : Set the new header
  387. // Return type : void 
  388. void CQListCtrlCtrl::OnHeaderChanged() 
  389. {
  390. Header(m_sHeader);
  391. SetModifiedFlag();
  392. }
  393. // Function name : CQListCtrlCtrl::OnMultiSelectChanged
  394. // Description     : Change the style case on m_bMultiSelect
  395. // Return type : void 
  396. void CQListCtrlCtrl::OnMultiSelectChanged() 
  397. {
  398. if (::IsWindow(GetSafeHwnd()))
  399. ModifyStyle(m_bMultiSelect ? LVS_SINGLESEL : 0, m_bMultiSelect ? 0 : LVS_SINGLESEL);
  400. SetModifiedFlag();
  401. }
  402. // Function name : CQListCtrlCtrl::ColumnFormatFromString
  403. // Description     : 
  404. // Return type : UINT 
  405. // Argument         : LCTSTR lpszFormat
  406. UINT CQListCtrlCtrl::ColumnFormatFromString(CString& sFormat)
  407. {
  408. if (sFormat.IsEmpty())
  409. return LVCFMT_LEFT;
  410. if (sFormat.CompareNoCase(CString(_T("Center")).Left(sFormat.GetLength())))
  411. return LVCFMT_CENTER;
  412. if (sFormat.CompareNoCase(CString(_T("Left")).Left(sFormat.GetLength())))
  413. return LVCFMT_LEFT;
  414. if (sFormat.CompareNoCase(CString(_T("Right")).Left(sFormat.GetLength())))
  415. return LVCFMT_RIGHT;
  416. return  LVCFMT_LEFT;
  417. }
  418. // Function name : CQListCtrlCtrl::Header
  419. // Description     : Set the header for control
  420. // Return type : void 
  421. // Argument         : LPCTSTR lpszHeader
  422. // The header is something like this. Column 1:Column 2:Column 3
  423. void CQListCtrlCtrl::Header(LPCTSTR lpszHeader)
  424. {
  425. CListCtrl* pListCtrl = GetListCtrl();
  426. if (::IsWindow(GetSafeHwnd()))
  427. {
  428. while (pListCtrl->DeleteColumn(0));
  429. CString sColumn; int i = 0;
  430. do {
  431. AfxExtractSubString(sColumn, lpszHeader,  i, _separatorColumnHeader);
  432. if (!sColumn.IsEmpty())
  433. {
  434. CString sName, sWidth, sJustify;
  435. AfxExtractSubString(sName, sColumn, 0, _separatorHeader);
  436. AfxExtractSubString(sWidth, sColumn, 1, _separatorHeader);
  437. AfxExtractSubString(sJustify, sColumn, 2, _separatorHeader);
  438. int nWidth = atoi(sWidth); nWidth = nWidth >= 0 ? nWidth : defaultColumnWidth;
  439. pListCtrl->InsertColumn(i, sName, ColumnFormatFromString(sJustify), nWidth);
  440. i++;
  441. }
  442. } while (!sColumn.IsEmpty());
  443. }
  444. }
  445. // Function name : CQListCtrlCtrl::OnSize
  446. // Description     : Change the size of control
  447. // Return type : void 
  448. // Argument         : UINT nType
  449. // Argument         : int cx
  450. // Argument         : int cy
  451. void CQListCtrlCtrl::OnSize(UINT nType, int cx, int cy) 
  452. {
  453. COleControl::OnSize(nType, cx, cy);
  454. Resize();
  455. }
  456. // Function name : CQListCtrlCtrl::GetVisibleCount
  457. // Description     : Return the number of visible items
  458. // Return type : int 
  459. int CQListCtrlCtrl::GetVisibleCount()
  460. {
  461. CRect rect; GetClientRect(rect);
  462. return rect.Height() / m_nItemHeight;
  463. }
  464. // Function name : CQListCtrlCtrl::Resize
  465. // Description     : Calculate the count of items loading. Is called after WM_SIZE occurs
  466. // Return type : void 
  467. void CQListCtrlCtrl::Resize()
  468. {
  469. if (::IsWindow(GetSafeHwnd()))
  470. {
  471. int nCountLoading = minCountLoading * int((GetVisibleCount() + minCountLoading) / minCountLoading);
  472. m_nCountLoading = max( m_nCountLoading, nCountLoading );
  473. OnItemsCountChanged();
  474. }
  475. }
  476. // Function name : CQListCtrlCtrl::OnItemsCountChanged
  477. // Description     : Control ask consumer to give number of items in the control. In this function
  478. // ww will calculate the vertical scroll bar
  479. // Return type : void 
  480. void CQListCtrlCtrl::OnItemsCountChanged()
  481. {
  482. int nVisible = GetVisibleCount();
  483. //If this control need vertical scroll bar, I will create one for this
  484. BOOL bCreated = ::IsWindow(m_sbVert.GetSafeHwnd());
  485. if ( m_nItemsCount >= nVisible)
  486. {
  487. CRect rect; GetClientRect(rect);
  488. rect.left = rect.right - GetSystemMetrics(SM_CXVSCROLL);
  489. if (CWnd* pHeader = GetDlgItem(0))
  490. if (pHeader->GetStyle() & WS_VISIBLE)
  491. {
  492. CRect r; pHeader->GetWindowRect(r);
  493. rect.top += r.Height();
  494. }
  495. if (!bCreated)
  496. bCreated = m_sbVert.Create( WS_CHILD | WS_VISIBLE | SBS_VERT, rect , this , IDSBVERT);
  497. else
  498. m_sbVert.MoveWindow(rect.left,rect.top, rect.Width(), rect.Height());
  499. if (bCreated)
  500. {
  501. SCROLLINFO sInfo;
  502.  sInfo.cbSize = sizeof(sInfo);
  503.  sInfo.fMask = SIF_ALL;
  504.  sInfo.nMin = 0;
  505.  sInfo.nMax = m_nItemsCount - 1;
  506.  sInfo.nPage = nVisible - 1;
  507.  sInfo.nPos = 0;
  508.  sInfo.nTrackPos = 0;
  509. m_sbVert.SetScrollInfo(&sInfo);
  510. }
  511. }
  512. else
  513. if (bCreated)
  514. m_sbVert.DestroyWindow();
  515. }
  516. // Function name : CQListCtrlCtrl::OnSetClientSite
  517. // Description     : Force this m_bMsgReflect to false, because thsi control must refect message
  518. // Return type : void 
  519. void CQListCtrlCtrl::OnSetClientSite( )
  520. {
  521. m_bMsgReflect = FALSE;
  522. }
  523. BOOL CQListCtrlCtrl::CreateControlWindow(HWND hWndParent, const CRect& rcPos, LPCRECT prcClipped)
  524. {
  525. //This function is already called if control receive the focus
  526. if (m_hWnd)
  527. return TRUE;
  528. return COleControl::CreateControlWindow(hWndParent, rcPos, prcClipped);
  529. }
  530. void CQListCtrlCtrl::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) 
  531. {
  532. if (GetStyle() & WS_VSCROLL)
  533. lpncsp->rgrc[0].right += GetSystemMetrics(SM_CXVSCROLL);
  534. COleControl::OnNcCalcSize(bCalcValidRects, lpncsp);
  535. }
  536. // Function name : CQListCtrlCtrl::OnShowWindow
  537. // Description     : 
  538. // Return type : void 
  539. // Argument         : BOOL bShow
  540. // Argument         : UINT nStatus
  541. void CQListCtrlCtrl::OnShowWindow(BOOL bShow, UINT nStatus) 
  542. {
  543. COleControl::OnShowWindow(bShow, nStatus);
  544. if (bShow)
  545. {
  546. }
  547. }
  548. // Function name : CQListCtrlCtrl::OnVScroll
  549. // Description     : 
  550. // Return type : void 
  551. // Argument         : UINT nSBCode
  552. // Argument         : UINT nPos
  553. // Argument         : CScrollBar* pScrollBar
  554. void CQListCtrlCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
  555. {
  556. if (pScrollBar == &m_sbVert)
  557. {
  558. CListCtrl* pListCtrl = GetListCtrl();
  559. int nHM = NULL, nStep = NULL;
  560. switch ( nSBCode )
  561. {
  562. case SB_LINEDOWN:
  563. case SB_PAGEDOWN:
  564. {
  565. nHM = m_nCountLoading;
  566. nStep = (nSBCode == SB_LINEDOWN ? 1 : nHM);
  567. }
  568. case SB_PAGEUP:
  569. case SB_LINEUP:
  570. {
  571. if (!nHM)
  572. {
  573. nHM = -m_nCountLoading;
  574. nStep = (nSBCode == SB_LINEUP ? -1 : nHM);
  575. }
  576. int nPosR = pListCtrl->GetTopIndex();
  577. LoadPartial( nPosR, nHM);
  578. pListCtrl->EnsureVisible(nPosR + nStep, FALSE);
  579. break;
  580. }
  581. case SB_THUMBPOSITION:
  582. {
  583. int nPosR = LoadPartial(nPos, m_nCountLoading);
  584. pListCtrl->EnsureVisible(nPosR, FALSE);
  585. break;
  586. }
  587. }
  588. pScrollBar->SetScrollPos(pListCtrl->GetTopIndex());
  589. }
  590. COleControl::OnVScroll(nSBCode, nPos, pScrollBar);
  591. }
  592. // Function name : CQListCtrlCtrl::OnKeyDown
  593. // Description     : 
  594. // Return type : void 
  595. // Argument         : UINT nChar
  596. // Argument         : UINT nRepCnt
  597. // Argument         : UINT nFlags
  598. void CQListCtrlCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  599. {
  600. if (m_pRectTracker == NULL)
  601. {
  602. BOOL bNeed = FALSE;
  603. switch (nChar)
  604. {
  605. case VK_PRIOR:
  606. case VK_NEXT:
  607. case VK_DOWN:
  608. case VK_UP:
  609. {
  610. LoadPartial(GetListCtrl()->GetTopIndex(), ( (nChar == VK_UP) || (nChar == VK_PRIOR) ? -1 : 1 ) * m_nCountLoading);
  611. bNeed = TRUE;
  612. break;
  613. }
  614. case VK_END:
  615. case VK_HOME:
  616. {
  617. LoadPartial(( nChar == VK_HOME ) ? 0 : GetCountItem() - m_nCountLoading, m_nCountLoading);
  618. bNeed = TRUE;
  619. break;
  620. }
  621. }
  622. COleControl::OnKeyDown(nChar, nRepCnt, nFlags);
  623. if (m_sbVert.GetSafeHwnd())
  624. if (bNeed)
  625. m_sbVert.SetScrollPos(GetListCtrl()->GetTopIndex());
  626. }
  627. }
  628. // Function name : CQListCtrlCtrl::OnNoHeaderChanged
  629. // Description     : 
  630. // Return type : void 
  631. void CQListCtrlCtrl::OnNoHeaderChanged() 
  632. {
  633. if (::IsWindow(GetSafeHwnd()))
  634. ModifyStyle(!m_bNoHeader ? LVS_NOCOLUMNHEADER : 0, m_bNoHeader ? LVS_NOCOLUMNHEADER : 0);
  635. SetModifiedFlag();
  636. }
  637. // Function name : CQListCtrlCtrl::OnSColumnChanged
  638. // Description     : 
  639. // Return type : void 
  640. void CQListCtrlCtrl::OnSColumnChanged() 
  641. {
  642. // Cannot be change in runtime
  643. }
  644. // Function name : CQListCtrlCtrl::InitItemsCount
  645. // Description     : This will generate an event to find number of items
  646. // Return type : void 
  647. void CQListCtrlCtrl::InitItemsCount() 
  648. {
  649. FireItemsCount(&m_nItemsCount);
  650. if (m_nItemsCount > 0)
  651. {
  652. OnItemsCountChanged();
  653. m_fctLoadFunction = LoadPartialListCtrl;
  654. // Load only visible items.
  655. LoadPartial(0, m_nCountLoading);
  656. }
  657. }
  658. // Function name : CQListCtrlCtrl::GetCountItem
  659. // Description     : return the real count of items
  660. // Return type : int 
  661. int CQListCtrlCtrl::GetCountItem()
  662. {
  663. return m_nItemsCount;
  664. }
  665. // Function name : AlreadyLoadPartialListCtrl
  666. // Description     : 
  667. // Return type : int 
  668. // Argument         : int nLineFrom
  669. // Argument         : int nHowMany
  670. int CQListCtrlCtrl::AlreadyLoadPartialListCtrl(int nLineFrom, int nHowMany)
  671. {
  672. return nLineFrom;
  673. }
  674. // Function name : CQListCtrlCtrl::Label
  675. // Description     : Load the text for the label and the lParam user data
  676. // Return type : LPCTSTR 
  677. // Argument         : int nLine
  678. // Argument         : LPARAM& lParamItem
  679. LPCTSTR CQListCtrlCtrl::Label(int nLine, LPARAM& lParamItem)
  680. {
  681. static CString text;
  682. BSTR bText = NULL;
  683. FireLoadLabel(nLine, &bText, &lParamItem);
  684. text = bText;
  685. ::SysFreeString(bText);
  686. return bText ? (LPCSTR)text : NULL;
  687. }
  688. // Function name : CQListCtrlCtrl::LoadRestOfLine
  689. // Description     : 
  690. // Return type : void 
  691. // Argument         : int nLine
  692. void CQListCtrlCtrl::LoadRestOfLine(int nLine, int nTrueLine)
  693. {
  694. LV_COLUMN lvColumn; lvColumn.mask = LVCF_WIDTH;
  695. int i = 0;
  696. CListCtrl* pListCtrl = GetListCtrl();
  697. while (pListCtrl->GetColumn(++i, &lvColumn))
  698. {
  699. BSTR bText = NULL;
  700. FireLoadSubItem(nTrueLine, i, &bText);
  701. pListCtrl->SetItemText(nLine,i, CString(bText));
  702. }
  703. }
  704. int CQListCtrlCtrl::LoadPartial(int nLineFrom, int nHowMany)
  705. {
  706. return (this->*m_fctLoadFunction)(nLineFrom, nHowMany);
  707. }
  708. int CQListCtrlCtrl::LoadPartialListCtrl(int nLineFrom, int nHowMany)
  709. {
  710. return m_QuickLoader.Load(nLineFrom, nHowMany);
  711. }
  712. //QSnapLoader implementation
  713. int CQListCtrlCtrl::QSnapLoader::SNodeItemsInfo::m_nCountRef = 0;
  714. // Function name : CQListCtrlCtrl::QSnapLoader::~QSnapLoader
  715. // Description     : virtual destructor. destory the double linked list.
  716. // Return type : 
  717. CQListCtrlCtrl::QSnapLoader::~QSnapLoader()
  718. {
  719. SNodeItemsInfo* pNodeNext = m_pFirstNode;
  720. while (pNodeNext)
  721. {
  722. SNodeItemsInfo* pNodeDelete = pNodeNext;
  723. pNodeNext = pNodeNext->m_pNextNode;
  724. delete pNodeDelete;
  725. };
  726. }
  727. // Function name : CQListCtrlCtrl::QSnapLoader::QSnapLoader
  728. // Description     : default constructor, create the first node in list
  729. // Return type : 
  730. CQListCtrlCtrl::QSnapLoader::QSnapLoader()
  731. {
  732. m_pFirstNode = new SNodeItemsInfo(0,0,0);
  733. }
  734. // Function name : CQListCtrlCtrl::QSnapLoader::SetParent
  735. // Description     : Set the parent of this structure, to be CQListCtrlCtrl that contains this structure(class).
  736. // Return type : void 
  737. // Argument         : CQListCtrlCtrl * pParent
  738. void CQListCtrlCtrl::QSnapLoader::SetParent(CQListCtrlCtrl* pParent)
  739. {
  740. m_pParent = pParent;
  741. }
  742. // Function name : CQListCtrlCtrl::QSnapLoader::GetListNodes
  743. // Description     : Give as string, all nodes from double linked list. Use for checking
  744. // Return type : CString 
  745. CString CQListCtrlCtrl::QSnapLoader::GetListNodes()
  746. {
  747. CString text;
  748. SNodeItemsInfo* pIncreaseNode = m_pFirstNode;
  749. int s = 0;
  750. while (pIncreaseNode)
  751. {
  752. CString t;
  753. t.Format(_T("(%i,%i,%i, [%i,%i])rn"), pIncreaseNode->m_nItemLine, pIncreaseNode->m_nCount, pIncreaseNode->m_nItemLB, pIncreaseNode->GetLastLine(), pIncreaseNode->GetLastItem());
  754. text += t;
  755. s += pIncreaseNode->m_nCount;
  756. pIncreaseNode = pIncreaseNode->m_pNextNode;
  757. }
  758. CString t;
  759. t.Format(_T("Count loaded: %i, Count items. listctrl() %i"), s, m_pParent->GetListCtrl()->GetItemCount());
  760. text += t;
  761. return text;
  762. }
  763. // Function name : CQListCtrlCtrl::QSnapLoader::Load
  764. // Description     : Function to load some items to this object
  765. // This function will call function Line of the parent object.
  766. // Return type : void 
  767. // Argument         : int nItemFrom
  768. // Argument         : int nHowMany
  769. // This function will return the real position into listctrl.
  770. int CQListCtrlCtrl::QSnapLoader::Load(int nItemFrom, int nHowMany)
  771. {
  772. int nIF = abs(nItemFrom + (nHowMany < 0 ? nHowMany : 0));
  773. int nHM = abs(nHowMany), nResult = nItemFrom;
  774. if (nHM = min(nHM, max(0,m_pParent->GetCountItem() - nIF)))
  775. {
  776. //Something must load
  777. ASSERT (nHM != NULL);
  778. SNodeItemsInfo* pNodeNext = m_pFirstNode;
  779. SNodeItemsInfo* pNodePrev = NULL;
  780. // Already the constructor was called
  781. ASSERT (pNodeNext);
  782. //Find the nodes ie pPrevNext->m_nItemLine <= nIF < pPrevNext->m_nItemLine
  783. while (pNodeNext && (nIF >= pNodeNext->m_nItemLine))
  784. {
  785. pNodePrev = pNodeNext;
  786. pNodeNext = pNodeNext->m_pNextNode;
  787. }
  788. // If in the first block , number of items count is equal with total number of items,
  789. // then this function will not be called again. The next function that will
  790. //be called will be AlreadyLoadPartialListCtrl.
  791. if (m_pFirstNode->m_nCount == m_pParent->GetCountItem())
  792. {
  793. m_pParent->m_fctLoadFunction = m_pParent->AlreadyLoadPartialListCtrl;
  794. // Fire an event to prevent the owner of this control, that all items was loaded
  795. m_pParent->FireAllItemsLoaded();
  796. return nItemFrom;
  797. }
  798. LPCTSTR lpszItemLB = NULL;
  799. LPARAM lParam = NULL;
  800. int nFirst = pNodePrev->GetLastLine(), nItem = pNodePrev->GetLastItem();
  801. CListCtrl* pListCtrl = m_pParent->GetListCtrl();
  802. nResult = pNodePrev->GetLastItem();
  803. if (pNodeNext == NULL)
  804. {
  805. // After the prev node do not exist another node.
  806. BOOL bEnd = TRUE;
  807. if (nIF > nFirst)
  808. {
  809. SNodeItemsInfo* sThis = pNodePrev;
  810. pNodePrev = new SNodeItemsInfo(nIF,0, nResult );
  811. sThis->m_pNextNode = pNodePrev;
  812. pNodePrev->m_pPrevNode = sThis;
  813. nFirst = nIF;
  814. bEnd = FALSE;
  815. }
  816. else
  817. {
  818. nResult = pNodePrev->m_nItemLB + nIF - pNodePrev->m_nItemLine;
  819. }
  820. int i = 0;
  821. for (i = 0; (lpszItemLB = m_pParent->Label(nFirst + i, lParam)) && (i < nHM); i++)
  822. {
  823. pListCtrl->SetItemData(nItem = pListCtrl->InsertItem(nItem, lpszItemLB), lParam);
  824. m_pParent->LoadRestOfLine(nItem, nFirst + i);
  825. pNodePrev->m_nCount++;
  826. nItem++;
  827. }
  828. }
  829. else
  830. {
  831. SNodeItemsInfo* pIncreaseNode = pNodeNext->m_pNextNode;
  832. int nDiff = pNodeNext->m_nItemLine - nFirst;
  833. ASSERT ( nDiff >= 0 );
  834. nItem = nResult; // first item that will be inserted
  835. // {...+..} ___ {...+..}
  836. if (nDiff <= nHM)
  837. {
  838. // The real nHM will be the diference between nHowMany - nDiff
  839. nHM = nDiff;
  840. // Try to restrict these node in only one.
  841. pNodePrev->m_nCount += pNodeNext->m_nCount + nHM;
  842. pNodePrev->m_pNextNode = pNodeNext->m_pNextNode;
  843. delete pNodeNext;
  844. nResult = pNodePrev->m_nItemLB + nIF - pNodePrev->m_nItemLine;
  845. }
  846. else
  847. {
  848. //      nFirst
  849. //        /--- > nHM --
  850. // {...+..} __+________{......}
  851. if (nIF < nFirst)
  852. {
  853. nResult = pNodePrev->m_nItemLB + nIF - pNodePrev->m_nItemLine;
  854. nFirst = pNodePrev->GetLastLine();
  855. pNodePrev->m_nCount += nHM;
  856. pIncreaseNode = pNodeNext;
  857. }
  858. // {......} ______+___ {...+...}
  859. else
  860. if (nIF + nHM >= pNodeNext->m_nItemLine)
  861. {
  862. nHM = pNodeNext->m_nItemLine - nIF;
  863. pNodeNext->m_nItemLine = nIF;
  864. pNodeNext->m_nCount += nHM;
  865. //pNodeNext->m_nItemLB remains constant
  866. nItem = pNodeNext->m_nItemLB;
  867. nFirst = nIF;
  868. nResult = pNodeNext->m_nItemLB;
  869. }
  870. // {......} __+____+___ {......}
  871. else
  872. {
  873. SNodeItemsInfo* sThis = new SNodeItemsInfo(nIF, nHM, nResult );
  874. sThis->m_pPrevNode = pNodePrev;
  875. sThis->m_pNextNode = pNodeNext;
  876. pNodePrev->m_pNextNode = sThis;
  877. pNodeNext->m_pPrevNode = sThis;
  878. nFirst = nIF;
  879. pIncreaseNode = pNodeNext;
  880. }
  881. }
  882. // if some items must insert, do it
  883. if (nHM > 0)
  884. {
  885. for (int i = 0; i < nHM; i++)
  886. {
  887. lpszItemLB = m_pParent->Label(nFirst + i, lParam);
  888. // while pNodePrev and pNodeNext exist !
  889. ASSERT (lpszItemLB);
  890. pListCtrl->SetItemData(nItem = pListCtrl->InsertItem(nItem, lpszItemLB), lParam);
  891. m_pParent->LoadRestOfLine(nItem, nFirst + i);
  892. nItem++;
  893. }
  894. while (pIncreaseNode)
  895. {
  896. pIncreaseNode->m_nItemLB += nHM;
  897. pIncreaseNode = pIncreaseNode->m_pNextNode;
  898. }
  899. }
  900. }
  901. }
  902. return nResult;
  903. }
  904. // Function name : CQListCtrlCtrl::QSnapLoader::GetItemLine
  905. // Description     : Return the Real line, converts from nItemLB
  906. // Return type : int 
  907. // Argument         : int nItemLB
  908. int CQListCtrlCtrl::QSnapLoader::GetItemLine(int nItemLB)
  909. {
  910. nItemLB = max(0,nItemLB);
  911. SNodeItemsInfo* pNodeNext = m_pFirstNode;
  912. while (pNodeNext && ( pNodeNext->m_nItemLB > nItemLB ))
  913. pNodeNext = pNodeNext->m_pNextNode;
  914. return pNodeNext->m_nItemLine  + nItemLB - pNodeNext->m_nItemLB;
  915. }