QListCtrlCtl.cpp
上传用户:cnjubao
上传日期:2007-01-02
资源大小:34k
文件大小:32k
源码类别:
ListView/ListBox
开发平台:
Visual C++
- /************************************
- REVISION LOG ENTRY
- Revision By: Mihai Filimon
- Revised on 11/2/98 3:29:27 PM
- Comments: QListCtrlCtl.cpp : Implementation of the CQListCtrlCtrl ActiveX Control class.
- ************************************/
- #include "stdafx.h"
- #include "QListCtrl.h"
- #include "QListCtrlCtl.h"
- #include "QListCtrlPpg.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- IMPLEMENT_DYNCREATE(CQListCtrlCtrl, COleControl)
- /////////////////////////////////////////////////////////////////////////////
- // Message map
- BEGIN_MESSAGE_MAP(CQListCtrlCtrl, COleControl)
- //{{AFX_MSG_MAP(CQListCtrlCtrl)
- ON_WM_CREATE()
- ON_WM_DRAWITEM_REFLECT()
- ON_WM_MEASUREITEM_REFLECT()
- ON_WM_SIZE()
- ON_WM_DESTROY()
- ON_WM_NCCALCSIZE()
- ON_WM_SHOWWINDOW()
- ON_WM_VSCROLL()
- ON_WM_KEYDOWN()
- //}}AFX_MSG_MAP
- ON_MESSAGE(OCM_COMMAND, OnOcmCommand)
- ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // Dispatch map
- BEGIN_DISPATCH_MAP(CQListCtrlCtrl, COleControl)
- //{{AFX_DISPATCH_MAP(CQListCtrlCtrl)
- DISP_PROPERTY_NOTIFY(CQListCtrlCtrl, "ItemHeight", m_nItemHeight, OnItemHeightChanged, VT_I4)
- DISP_PROPERTY_NOTIFY(CQListCtrlCtrl, "GridLines", m_bGridLines, OnGridLinesChanged, VT_BOOL)
- DISP_PROPERTY_NOTIFY(CQListCtrlCtrl, "Header", m_sHeader, OnHeaderChanged, VT_BSTR)
- DISP_PROPERTY_NOTIFY(CQListCtrlCtrl, "MultiSelect", m_bMultiSelect, OnMultiSelectChanged, VT_BOOL)
- DISP_PROPERTY_NOTIFY(CQListCtrlCtrl, "NoHeader", m_bNoHeader, OnNoHeaderChanged, VT_BOOL)
- DISP_PROPERTY_NOTIFY(CQListCtrlCtrl, "SColumn", m_bSColumn, OnSColumnChanged, VT_BOOL)
- DISP_FUNCTION(CQListCtrlCtrl, "InitItemsCount", InitItemsCount, VT_EMPTY, VTS_NONE)
- DISP_STOCKPROP_FONT()
- //}}AFX_DISPATCH_MAP
- DISP_FUNCTION_ID(CQListCtrlCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
- END_DISPATCH_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // Event map
- BEGIN_EVENT_MAP(CQListCtrlCtrl, COleControl)
- //{{AFX_EVENT_MAP(CQListCtrlCtrl)
- EVENT_CUSTOM("ItemsCount", FireItemsCount, VTS_PI4)
- EVENT_CUSTOM("AllItemsLoaded", FireAllItemsLoaded, VTS_NONE)
- EVENT_CUSTOM("LoadLabel", FireLoadLabel, VTS_I4 VTS_PBSTR VTS_PI4)
- EVENT_CUSTOM("LoadSubItem", FireLoadSubItem, VTS_I4 VTS_I4 VTS_PBSTR)
- //}}AFX_EVENT_MAP
- END_EVENT_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // Property pages
- // TODO: Add more property pages as needed. Remember to increase the count!
- BEGIN_PROPPAGEIDS(CQListCtrlCtrl, 2)
- PROPPAGEID(CQListCtrlPropPage::guid)
- PROPPAGEID(CLSID_CFontPropPage )
- END_PROPPAGEIDS(CQListCtrlCtrl)
- /////////////////////////////////////////////////////////////////////////////
- // Initialize class factory and guid
- IMPLEMENT_OLECREATE_EX(CQListCtrlCtrl, "QLISTCTRL.QListCtrlCtrl.1",
- 0xbfcc1bc6, 0x7257, 0x11d2, 0x86, 0xe6, 0, 0x40, 0x5, 0x5c, 0x8, 0xd9)
- /////////////////////////////////////////////////////////////////////////////
- // Type library ID and version
- IMPLEMENT_OLETYPELIB(CQListCtrlCtrl, _tlid, _wVerMajor, _wVerMinor)
- /////////////////////////////////////////////////////////////////////////////
- // Interface IDs
- const IID BASED_CODE IID_DQListCtrl =
- { 0xbfcc1bc4, 0x7257, 0x11d2, { 0x86, 0xe6, 0, 0x40, 0x5, 0x5c, 0x8, 0xd9 } };
- const IID BASED_CODE IID_DQListCtrlEvents =
- { 0xbfcc1bc5, 0x7257, 0x11d2, { 0x86, 0xe6, 0, 0x40, 0x5, 0x5c, 0x8, 0xd9 } };
- /////////////////////////////////////////////////////////////////////////////
- // Control type information
- static const DWORD BASED_CODE _dwQListCtrlOleMisc =
- OLEMISC_ACTIVATEWHENVISIBLE |
- OLEMISC_SETCLIENTSITEFIRST |
- OLEMISC_INSIDEOUT |
- OLEMISC_CANTLINKINSIDE |
- OLEMISC_RECOMPOSEONRESIZE;
- IMPLEMENT_OLECTLTYPE(CQListCtrlCtrl, IDS_QLISTCTRL, _dwQListCtrlOleMisc)
- /////////////////////////////////////////////////////////////////////////////
- // CQListCtrlCtrl::CQListCtrlCtrlFactory::UpdateRegistry -
- // Adds or removes system registry entries for CQListCtrlCtrl
- // Function name : CQListCtrlCtrl::CQListCtrlCtrlFactory::UpdateRegistry
- // Description : Update the registry
- // Return type : BOOL
- // Argument : BOOL bRegister
- BOOL CQListCtrlCtrl::CQListCtrlCtrlFactory::UpdateRegistry(BOOL bRegister)
- {
- // TODO: Verify that your control follows apartment-model threading rules.
- // Refer to MFC TechNote 64 for more information.
- // If your control does not conform to the apartment-model rules, then
- // you must modify the code below, changing the 6th parameter from
- // afxRegApartmentThreading to 0.
- if (bRegister)
- return AfxOleRegisterControlClass(
- AfxGetInstanceHandle(),
- m_clsid,
- m_lpszProgID,
- IDS_QLISTCTRL,
- IDB_QLISTCTRL,
- afxRegApartmentThreading,
- _dwQListCtrlOleMisc,
- _tlid,
- _wVerMajor,
- _wVerMinor);
- else
- return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
- }
- /////////////////////////////////////////////////////////////////////////////
- // Licensing strings
- static const TCHAR BASED_CODE _szLicFileName[] = _T("QListCtrl.lic");
- static const WCHAR BASED_CODE _szLicString[] =
- L"Copyright (c) 1998 Filimon";
- /////////////////////////////////////////////////////////////////////////////
- // CQListCtrlCtrl::CQListCtrlCtrlFactory::VerifyUserLicense -
- // Checks for existence of a user license
- // Function name : CQListCtrlCtrl::CQListCtrlCtrlFactory::VerifyUserLicense
- // Description : Verify license
- // Return type : BOOL
- BOOL CQListCtrlCtrl::CQListCtrlCtrlFactory::VerifyUserLicense()
- {
- return AfxVerifyLicFile(AfxGetInstanceHandle(), _szLicFileName,
- _szLicString);
- }
- /////////////////////////////////////////////////////////////////////////////
- // CQListCtrlCtrl::CQListCtrlCtrlFactory::GetLicenseKey -
- // Returns a runtime licensing key
- BOOL CQListCtrlCtrl::CQListCtrlCtrlFactory::GetLicenseKey(DWORD dwReserved,
- BSTR FAR* pbstrKey)
- {
- if (pbstrKey == NULL)
- return FALSE;
- *pbstrKey = SysAllocString(_szLicString);
- return (*pbstrKey != NULL);
- }
- /////////////////////////////////////////////////////////////////////////////
- // CQListCtrlCtrl::CQListCtrlCtrl - Constructor
- // Function name : CQListCtrlCtrl::CQListCtrlCtrl
- // Description : Default constructor
- // Return type :
- CQListCtrlCtrl::CQListCtrlCtrl()
- {
- InitializeIIDs(&IID_DQListCtrl, &IID_DQListCtrlEvents);
- m_nItemsCount = -1;
- m_nCountLoading = 0;
- m_QuickLoader.SetParent(this);
- m_fctLoadFunction = NULL;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CQListCtrlCtrl::~CQListCtrlCtrl - Destructor
- // Function name : CQListCtrlCtrl::~CQListCtrlCtrl
- // Description :
- // Return type :
- CQListCtrlCtrl::~CQListCtrlCtrl()
- {
- // TODO: Cleanup your control's instance data here.
- }
- // Function name : CQListCtrlCtrl::GetListCtrl
- // Description :
- // Return type : CListCtrl*
- CListCtrl* CQListCtrlCtrl::GetListCtrl()
- {
- return (CListCtrl*)this;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CQListCtrlCtrl::OnDraw - Drawing function
- void CQListCtrlCtrl::OnDraw(
- CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
- {
- if (m_hWnd != NULL)
- {
- CRect rcClient;
- GetClientRect(&rcClient);
- if (rcClient.Size() != rcBounds.Size())
- {
- pdc->SetMapMode(MM_ANISOTROPIC);
- pdc->SetWindowExt(rcClient.right, rcClient.bottom);
- pdc->SetViewportExt(rcBounds.Size());
- }
- pdc->SetWindowOrg(0, 0);
- pdc->SetViewportOrg(rcBounds.left, rcBounds.top);
- ::CallWindowProc(*GetSuperWndProcAddr(), m_hWnd, WM_PRINT, (WPARAM)(pdc->m_hDC), (LPARAM)(PRF_ERASEBKGND | PRF_CLIENT | PRF_CHILDREN | PRF_NONCLIENT));
- }
- else
- {
- CFont* pFont = SelectStockFont(pdc);
- CString text;
- text.Format(_T("QListCtrl %i.%i Control"), _wVerMajor, _wVerMinor);
- pdc->DrawText(text, CRect(rcInvalid), DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- pdc->SelectObject(pFont);
- }
- return;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CQListCtrlCtrl::DoPropExchange - Persistence support
- // Function name : CQListCtrlCtrl::DoPropExchange
- // Description : Save/Load the properties
- // Return type : void
- // Argument : CPropExchange* pPX
- void CQListCtrlCtrl::DoPropExchange(CPropExchange* pPX)
- {
- ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
- COleControl::DoPropExchange(pPX);
- PX_Long(pPX, _T("ItemHeight"), m_nItemHeight, defaultItemHeight);
- PX_Bool(pPX, _T("GridLines"), m_bGridLines, TRUE);
- PX_Bool(pPX, _T("MultiSelect"), m_bMultiSelect, TRUE);
- PX_String(pPX, _T("Header"), m_sHeader, _T(""));
- PX_Bool(pPX, _T("NoHeader"), m_bNoHeader, FALSE);
- PX_Bool(pPX, _T("SColumn"), m_bSColumn, FALSE);
- }
- /////////////////////////////////////////////////////////////////////////////
- // CQListCtrlCtrl::OnResetState - Reset control to default state
- // Function name : CQListCtrlCtrl::OnResetState
- // Description : On default value
- // Return type : void
- void CQListCtrlCtrl::OnResetState()
- {
- COleControl::OnResetState(); // Resets defaults found in DoPropExchange
- }
- /////////////////////////////////////////////////////////////////////////////
- // CQListCtrlCtrl::AboutBox - Display an "About" box to the user
- // Function name : CQListCtrlCtrl::AboutBox
- // Description : do an about box
- // Return type : void
- void CQListCtrlCtrl::AboutBox()
- {
- CDialog dlgAbout(IDD_ABOUTBOX_QLISTCTRL);
- // dlgAbout.DoModal();
- LV_COLUMN lColumn; lColumn.mask = LVCF_FMT;
- for (int j = 0; j < 32; j++)
- {
- int nItem = GetListCtrl()->InsertItem(0, RandomString());
- for (int i = 1; GetListCtrl()->GetColumn(i, &lColumn); i++)
- GetListCtrl()->SetItemText(nItem, i, RandomString());
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- // CQListCtrlCtrl::PreCreateWindow - Modify parameters for CreateWindowEx
- // Function name : CQListCtrlCtrl::PreCreateWindow
- // Description : Create OLEControl as SysListView32
- // Return type : BOOL
- // Argument : CREATESTRUCT& cs
- BOOL CQListCtrlCtrl::PreCreateWindow(CREATESTRUCT& cs)
- {
- cs.lpszClass = _T("SysListView32");
- cs.style |= defaultStyles | (m_bSColumn ? LVS_NOSORTHEADER : 0);
- return COleControl::PreCreateWindow(cs);
- }
- /////////////////////////////////////////////////////////////////////////////
- // CQListCtrlCtrl::IsSubclassedControl - This is a subclassed control
- // Function name : CQListCtrlCtrl::IsSubclassedControl
- // Description :
- // Return type : BOOL
- BOOL CQListCtrlCtrl::IsSubclassedControl()
- {
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CQListCtrlCtrl::OnOcmCommand - Handle command messages
- LRESULT CQListCtrlCtrl::OnOcmCommand(WPARAM wParam, LPARAM lParam)
- {
- #ifdef _WIN32
- WORD wNotifyCode = HIWORD(wParam);
- #else
- WORD wNotifyCode = HIWORD(lParam);
- #endif
- return 0;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CQListCtrlCtrl message handlers
- // Function name : CQListCtrlCtrl::OnInit
- // Description :
- // Return type : void
- void CQListCtrlCtrl::OnInit()
- {
- OnGridLinesChanged();
- OnHeaderChanged();
- OnMultiSelectChanged();
- OnNoHeaderChanged();
- OnSColumnChanged();
- }
- // Function name : CQListCtrlCtrl::OnDestroy
- // Description : On destroy we will uninstall hook procedure
- // Return type : void
- void CQListCtrlCtrl::OnDestroy()
- {
- COleControl::OnDestroy();
- }
- // Function name : CQListCtrlCtrl::OnCreate
- // Description : Call to set opr not the grid lines of control
- // Return type : int
- // Argument : LPCREATESTRUCT lpCreateStruct
- int CQListCtrlCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- if (COleControl::OnCreate(lpCreateStruct) == -1)
- return -1;
- ASSERT (GetStyle() & (LVS_REPORT | LVS_OWNERDRAWFIXED) );
- OnInit();
- return 0;
- }
- // Function name : CQListCtrlCtrl::MeasureItem
- // Description : Measure the item
- // Return type : void
- // Argument : LPMEASUREITEMSTRUCT lpMeasureItemStruct
- void CQListCtrlCtrl::MeasureItem( LPMEASUREITEMSTRUCT lpMeasureItemStruct )
- {
- lpMeasureItemStruct->itemHeight = m_nItemHeight;
- }
- // Function name : CQListCtrlCtrl::FormatColumn
- // Description : Return the draw format for iColumn
- // Return type : UINT
- // Argument : int iColumn
- UINT CQListCtrlCtrl::FormatColumn(int iColumn)
- {
- LV_COLUMN lColumn; lColumn.mask = LVCF_FMT;
- if (GetListCtrl()->GetColumn(iColumn, &lColumn))
- return lColumn.fmt & LVCFMT_JUSTIFYMASK;
- return 0;
- }
- #define formatDrawText DT_VCENTER | DT_SINGLELINE
- // Function name : CQListCtrlCtrl::DrawItem
- // Description : Drawing an item
- // Return type : void
- // Argument : LPDRAWITEMSTRUCT lpDrawItemStruct
- void CQListCtrlCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
- {
- CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
- CListCtrl* pListCtrl = GetListCtrl();
- CRect rectDraw(lpDrawItemStruct->rcItem);
- CRect rectItem(rectDraw);
- int nItem = lpDrawItemStruct->itemID;
- CRect rectAll; pListCtrl->GetItemRect(nItem, rectAll, LVIR_BOUNDS);
- CRect rectLabel; pListCtrl->GetItemRect(nItem, rectLabel, LVIR_LABEL);
- BOOL bFocused = GetFocus() && (pListCtrl->GetItemState(nItem, LVIS_FOCUSED) == LVIS_FOCUSED);
- BOOL bSelected = pListCtrl->GetItemState(nItem, LVIS_SELECTED) == LVIS_SELECTED;
- LV_COLUMN lColumn; lColumn.mask = LVCF_WIDTH;
- rectItem.left += 2;
- pDC->SetTextColor(bSelected & bFocused ? RGB(255,255,255) : RGB(0,0,0));
- CBrush brush(bSelected ? (bFocused ? RGB(0,0,128) : RGB(192,192,192)) : RGB(255,255,255));
- pDC->FillRect(rectAll, &brush);
- // Select the item font
- CFont* pFont = SelectStockFont(pDC);
- for (int i = 0; pListCtrl->GetColumn(i, &lColumn); i++, rectItem.left += lColumn.cx + 2)
- {
- rectItem.right = rectItem.left + lColumn.cx - 2;
- pDC->DrawText(pListCtrl->GetItemText(nItem, i), rectItem, formatDrawText | FormatColumn(i));
- }
- pDC->SelectObject(pFont);
- pDC->SetTextColor(RGB(0,0,0));
- // Deselect the item font
- if (bFocused)
- {
- rectAll.InflateRect(0,-2);
- rectAll.bottom++;
- pDC->FrameRect(rectAll, &CBrush(RGB(0,0,0)));
- }
- }
- // Function name : CQListCtrlCtrl::OnItemHeightChanged
- // Description : Set the item height
- // Return type : void
- void CQListCtrlCtrl::OnItemHeightChanged()
- {
- m_nItemHeight = abs(m_nItemHeight);
- m_nItemHeight = max(1,m_nItemHeight);
- ASSERT (m_nItemHeight > 0);
- SetModifiedFlag();
- }
- // Function name : CQListCtrlCtrl::OnGridLinesChanged
- // Description : Set or not the grid lines
- // Return type : void
- void CQListCtrlCtrl::OnGridLinesChanged()
- {
- if (::IsWindow(GetSafeHwnd()))
- ListView_SetExtendedListViewStyle(m_hWnd, (m_bGridLines ? LVS_EX_GRIDLINES : 0) | LVS_EX_FULLROWSELECT );
- SetModifiedFlag();
- }
- // Function name : CQListCtrlCtrl::OnHeaderChanged
- // Description : Set the new header
- // Return type : void
- void CQListCtrlCtrl::OnHeaderChanged()
- {
- Header(m_sHeader);
- SetModifiedFlag();
- }
- // Function name : CQListCtrlCtrl::OnMultiSelectChanged
- // Description : Change the style case on m_bMultiSelect
- // Return type : void
- void CQListCtrlCtrl::OnMultiSelectChanged()
- {
- if (::IsWindow(GetSafeHwnd()))
- ModifyStyle(m_bMultiSelect ? LVS_SINGLESEL : 0, m_bMultiSelect ? 0 : LVS_SINGLESEL);
- SetModifiedFlag();
- }
- // Function name : CQListCtrlCtrl::ColumnFormatFromString
- // Description :
- // Return type : UINT
- // Argument : LCTSTR lpszFormat
- UINT CQListCtrlCtrl::ColumnFormatFromString(CString& sFormat)
- {
- if (sFormat.IsEmpty())
- return LVCFMT_LEFT;
- if (sFormat.CompareNoCase(CString(_T("Center")).Left(sFormat.GetLength())))
- return LVCFMT_CENTER;
- if (sFormat.CompareNoCase(CString(_T("Left")).Left(sFormat.GetLength())))
- return LVCFMT_LEFT;
- if (sFormat.CompareNoCase(CString(_T("Right")).Left(sFormat.GetLength())))
- return LVCFMT_RIGHT;
- return LVCFMT_LEFT;
- }
- // Function name : CQListCtrlCtrl::Header
- // Description : Set the header for control
- // Return type : void
- // Argument : LPCTSTR lpszHeader
- // The header is something like this. Column 1:Column 2:Column 3
- void CQListCtrlCtrl::Header(LPCTSTR lpszHeader)
- {
- CListCtrl* pListCtrl = GetListCtrl();
- if (::IsWindow(GetSafeHwnd()))
- {
- while (pListCtrl->DeleteColumn(0));
- CString sColumn; int i = 0;
- do {
- AfxExtractSubString(sColumn, lpszHeader, i, _separatorColumnHeader);
- if (!sColumn.IsEmpty())
- {
- CString sName, sWidth, sJustify;
- AfxExtractSubString(sName, sColumn, 0, _separatorHeader);
- AfxExtractSubString(sWidth, sColumn, 1, _separatorHeader);
- AfxExtractSubString(sJustify, sColumn, 2, _separatorHeader);
- int nWidth = atoi(sWidth); nWidth = nWidth >= 0 ? nWidth : defaultColumnWidth;
- pListCtrl->InsertColumn(i, sName, ColumnFormatFromString(sJustify), nWidth);
- i++;
- }
- } while (!sColumn.IsEmpty());
- }
- }
- // Function name : CQListCtrlCtrl::OnSize
- // Description : Change the size of control
- // Return type : void
- // Argument : UINT nType
- // Argument : int cx
- // Argument : int cy
- void CQListCtrlCtrl::OnSize(UINT nType, int cx, int cy)
- {
- COleControl::OnSize(nType, cx, cy);
- Resize();
- }
- // Function name : CQListCtrlCtrl::GetVisibleCount
- // Description : Return the number of visible items
- // Return type : int
- int CQListCtrlCtrl::GetVisibleCount()
- {
- CRect rect; GetClientRect(rect);
- return rect.Height() / m_nItemHeight;
- }
- // Function name : CQListCtrlCtrl::Resize
- // Description : Calculate the count of items loading. Is called after WM_SIZE occurs
- // Return type : void
- void CQListCtrlCtrl::Resize()
- {
- if (::IsWindow(GetSafeHwnd()))
- {
- int nCountLoading = minCountLoading * int((GetVisibleCount() + minCountLoading) / minCountLoading);
- m_nCountLoading = max( m_nCountLoading, nCountLoading );
- OnItemsCountChanged();
- }
- }
- // Function name : CQListCtrlCtrl::OnItemsCountChanged
- // Description : Control ask consumer to give number of items in the control. In this function
- // ww will calculate the vertical scroll bar
- // Return type : void
- void CQListCtrlCtrl::OnItemsCountChanged()
- {
- int nVisible = GetVisibleCount();
- //If this control need vertical scroll bar, I will create one for this
- BOOL bCreated = ::IsWindow(m_sbVert.GetSafeHwnd());
- if ( m_nItemsCount >= nVisible)
- {
- CRect rect; GetClientRect(rect);
- rect.left = rect.right - GetSystemMetrics(SM_CXVSCROLL);
- if (CWnd* pHeader = GetDlgItem(0))
- if (pHeader->GetStyle() & WS_VISIBLE)
- {
- CRect r; pHeader->GetWindowRect(r);
- rect.top += r.Height();
- }
- if (!bCreated)
- bCreated = m_sbVert.Create( WS_CHILD | WS_VISIBLE | SBS_VERT, rect , this , IDSBVERT);
- else
- m_sbVert.MoveWindow(rect.left,rect.top, rect.Width(), rect.Height());
- if (bCreated)
- {
- SCROLLINFO sInfo;
- sInfo.cbSize = sizeof(sInfo);
- sInfo.fMask = SIF_ALL;
- sInfo.nMin = 0;
- sInfo.nMax = m_nItemsCount - 1;
- sInfo.nPage = nVisible - 1;
- sInfo.nPos = 0;
- sInfo.nTrackPos = 0;
- m_sbVert.SetScrollInfo(&sInfo);
- }
- }
- else
- if (bCreated)
- m_sbVert.DestroyWindow();
- }
- // Function name : CQListCtrlCtrl::OnSetClientSite
- // Description : Force this m_bMsgReflect to false, because thsi control must refect message
- // Return type : void
- void CQListCtrlCtrl::OnSetClientSite( )
- {
- m_bMsgReflect = FALSE;
- }
- BOOL CQListCtrlCtrl::CreateControlWindow(HWND hWndParent, const CRect& rcPos, LPCRECT prcClipped)
- {
- //This function is already called if control receive the focus
- if (m_hWnd)
- return TRUE;
- return COleControl::CreateControlWindow(hWndParent, rcPos, prcClipped);
- }
- void CQListCtrlCtrl::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
- {
- if (GetStyle() & WS_VSCROLL)
- lpncsp->rgrc[0].right += GetSystemMetrics(SM_CXVSCROLL);
- COleControl::OnNcCalcSize(bCalcValidRects, lpncsp);
- }
- // Function name : CQListCtrlCtrl::OnShowWindow
- // Description :
- // Return type : void
- // Argument : BOOL bShow
- // Argument : UINT nStatus
- void CQListCtrlCtrl::OnShowWindow(BOOL bShow, UINT nStatus)
- {
- COleControl::OnShowWindow(bShow, nStatus);
- if (bShow)
- {
- }
- }
- // Function name : CQListCtrlCtrl::OnVScroll
- // Description :
- // Return type : void
- // Argument : UINT nSBCode
- // Argument : UINT nPos
- // Argument : CScrollBar* pScrollBar
- void CQListCtrlCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
- {
- if (pScrollBar == &m_sbVert)
- {
- CListCtrl* pListCtrl = GetListCtrl();
- int nHM = NULL, nStep = NULL;
- switch ( nSBCode )
- {
- case SB_LINEDOWN:
- case SB_PAGEDOWN:
- {
- nHM = m_nCountLoading;
- nStep = (nSBCode == SB_LINEDOWN ? 1 : nHM);
- }
- case SB_PAGEUP:
- case SB_LINEUP:
- {
- if (!nHM)
- {
- nHM = -m_nCountLoading;
- nStep = (nSBCode == SB_LINEUP ? -1 : nHM);
- }
- int nPosR = pListCtrl->GetTopIndex();
- LoadPartial( nPosR, nHM);
- pListCtrl->EnsureVisible(nPosR + nStep, FALSE);
- break;
- }
- case SB_THUMBPOSITION:
- {
- int nPosR = LoadPartial(nPos, m_nCountLoading);
- pListCtrl->EnsureVisible(nPosR, FALSE);
- break;
- }
- }
- pScrollBar->SetScrollPos(pListCtrl->GetTopIndex());
- }
- COleControl::OnVScroll(nSBCode, nPos, pScrollBar);
- }
- // Function name : CQListCtrlCtrl::OnKeyDown
- // Description :
- // Return type : void
- // Argument : UINT nChar
- // Argument : UINT nRepCnt
- // Argument : UINT nFlags
- void CQListCtrlCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
- {
- if (m_pRectTracker == NULL)
- {
- BOOL bNeed = FALSE;
- switch (nChar)
- {
- case VK_PRIOR:
- case VK_NEXT:
- case VK_DOWN:
- case VK_UP:
- {
- LoadPartial(GetListCtrl()->GetTopIndex(), ( (nChar == VK_UP) || (nChar == VK_PRIOR) ? -1 : 1 ) * m_nCountLoading);
- bNeed = TRUE;
- break;
- }
- case VK_END:
- case VK_HOME:
- {
- LoadPartial(( nChar == VK_HOME ) ? 0 : GetCountItem() - m_nCountLoading, m_nCountLoading);
- bNeed = TRUE;
- break;
- }
- }
- COleControl::OnKeyDown(nChar, nRepCnt, nFlags);
- if (m_sbVert.GetSafeHwnd())
- if (bNeed)
- m_sbVert.SetScrollPos(GetListCtrl()->GetTopIndex());
- }
- }
- // Function name : CQListCtrlCtrl::OnNoHeaderChanged
- // Description :
- // Return type : void
- void CQListCtrlCtrl::OnNoHeaderChanged()
- {
- if (::IsWindow(GetSafeHwnd()))
- ModifyStyle(!m_bNoHeader ? LVS_NOCOLUMNHEADER : 0, m_bNoHeader ? LVS_NOCOLUMNHEADER : 0);
- SetModifiedFlag();
- }
- // Function name : CQListCtrlCtrl::OnSColumnChanged
- // Description :
- // Return type : void
- void CQListCtrlCtrl::OnSColumnChanged()
- {
- // Cannot be change in runtime
- }
- // Function name : CQListCtrlCtrl::InitItemsCount
- // Description : This will generate an event to find number of items
- // Return type : void
- void CQListCtrlCtrl::InitItemsCount()
- {
- FireItemsCount(&m_nItemsCount);
- if (m_nItemsCount > 0)
- {
- OnItemsCountChanged();
- m_fctLoadFunction = LoadPartialListCtrl;
- // Load only visible items.
- LoadPartial(0, m_nCountLoading);
- }
- }
- // Function name : CQListCtrlCtrl::GetCountItem
- // Description : return the real count of items
- // Return type : int
- int CQListCtrlCtrl::GetCountItem()
- {
- return m_nItemsCount;
- }
- // Function name : AlreadyLoadPartialListCtrl
- // Description :
- // Return type : int
- // Argument : int nLineFrom
- // Argument : int nHowMany
- int CQListCtrlCtrl::AlreadyLoadPartialListCtrl(int nLineFrom, int nHowMany)
- {
- return nLineFrom;
- }
- // Function name : CQListCtrlCtrl::Label
- // Description : Load the text for the label and the lParam user data
- // Return type : LPCTSTR
- // Argument : int nLine
- // Argument : LPARAM& lParamItem
- LPCTSTR CQListCtrlCtrl::Label(int nLine, LPARAM& lParamItem)
- {
- static CString text;
- BSTR bText = NULL;
- FireLoadLabel(nLine, &bText, &lParamItem);
- text = bText;
- ::SysFreeString(bText);
- return bText ? (LPCSTR)text : NULL;
- }
- // Function name : CQListCtrlCtrl::LoadRestOfLine
- // Description :
- // Return type : void
- // Argument : int nLine
- void CQListCtrlCtrl::LoadRestOfLine(int nLine, int nTrueLine)
- {
- LV_COLUMN lvColumn; lvColumn.mask = LVCF_WIDTH;
- int i = 0;
- CListCtrl* pListCtrl = GetListCtrl();
- while (pListCtrl->GetColumn(++i, &lvColumn))
- {
- BSTR bText = NULL;
- FireLoadSubItem(nTrueLine, i, &bText);
- pListCtrl->SetItemText(nLine,i, CString(bText));
- }
- }
- int CQListCtrlCtrl::LoadPartial(int nLineFrom, int nHowMany)
- {
- return (this->*m_fctLoadFunction)(nLineFrom, nHowMany);
- }
- int CQListCtrlCtrl::LoadPartialListCtrl(int nLineFrom, int nHowMany)
- {
- return m_QuickLoader.Load(nLineFrom, nHowMany);
- }
- //QSnapLoader implementation
- int CQListCtrlCtrl::QSnapLoader::SNodeItemsInfo::m_nCountRef = 0;
- // Function name : CQListCtrlCtrl::QSnapLoader::~QSnapLoader
- // Description : virtual destructor. destory the double linked list.
- // Return type :
- CQListCtrlCtrl::QSnapLoader::~QSnapLoader()
- {
- SNodeItemsInfo* pNodeNext = m_pFirstNode;
- while (pNodeNext)
- {
- SNodeItemsInfo* pNodeDelete = pNodeNext;
- pNodeNext = pNodeNext->m_pNextNode;
- delete pNodeDelete;
- };
- }
- // Function name : CQListCtrlCtrl::QSnapLoader::QSnapLoader
- // Description : default constructor, create the first node in list
- // Return type :
- CQListCtrlCtrl::QSnapLoader::QSnapLoader()
- {
- m_pFirstNode = new SNodeItemsInfo(0,0,0);
- }
- // Function name : CQListCtrlCtrl::QSnapLoader::SetParent
- // Description : Set the parent of this structure, to be CQListCtrlCtrl that contains this structure(class).
- // Return type : void
- // Argument : CQListCtrlCtrl * pParent
- void CQListCtrlCtrl::QSnapLoader::SetParent(CQListCtrlCtrl* pParent)
- {
- m_pParent = pParent;
- }
- // Function name : CQListCtrlCtrl::QSnapLoader::GetListNodes
- // Description : Give as string, all nodes from double linked list. Use for checking
- // Return type : CString
- CString CQListCtrlCtrl::QSnapLoader::GetListNodes()
- {
- CString text;
- SNodeItemsInfo* pIncreaseNode = m_pFirstNode;
- int s = 0;
- while (pIncreaseNode)
- {
- CString t;
- t.Format(_T("(%i,%i,%i, [%i,%i])rn"), pIncreaseNode->m_nItemLine, pIncreaseNode->m_nCount, pIncreaseNode->m_nItemLB, pIncreaseNode->GetLastLine(), pIncreaseNode->GetLastItem());
- text += t;
- s += pIncreaseNode->m_nCount;
- pIncreaseNode = pIncreaseNode->m_pNextNode;
- }
- CString t;
- t.Format(_T("Count loaded: %i, Count items. listctrl() %i"), s, m_pParent->GetListCtrl()->GetItemCount());
- text += t;
- return text;
- }
- // Function name : CQListCtrlCtrl::QSnapLoader::Load
- // Description : Function to load some items to this object
- // This function will call function Line of the parent object.
- // Return type : void
- // Argument : int nItemFrom
- // Argument : int nHowMany
- // This function will return the real position into listctrl.
- int CQListCtrlCtrl::QSnapLoader::Load(int nItemFrom, int nHowMany)
- {
- int nIF = abs(nItemFrom + (nHowMany < 0 ? nHowMany : 0));
- int nHM = abs(nHowMany), nResult = nItemFrom;
- if (nHM = min(nHM, max(0,m_pParent->GetCountItem() - nIF)))
- {
- //Something must load
- ASSERT (nHM != NULL);
- SNodeItemsInfo* pNodeNext = m_pFirstNode;
- SNodeItemsInfo* pNodePrev = NULL;
- // Already the constructor was called
- ASSERT (pNodeNext);
- //Find the nodes ie pPrevNext->m_nItemLine <= nIF < pPrevNext->m_nItemLine
- while (pNodeNext && (nIF >= pNodeNext->m_nItemLine))
- {
- pNodePrev = pNodeNext;
- pNodeNext = pNodeNext->m_pNextNode;
- }
- // If in the first block , number of items count is equal with total number of items,
- // then this function will not be called again. The next function that will
- //be called will be AlreadyLoadPartialListCtrl.
- if (m_pFirstNode->m_nCount == m_pParent->GetCountItem())
- {
- m_pParent->m_fctLoadFunction = m_pParent->AlreadyLoadPartialListCtrl;
- // Fire an event to prevent the owner of this control, that all items was loaded
- m_pParent->FireAllItemsLoaded();
- return nItemFrom;
- }
- LPCTSTR lpszItemLB = NULL;
- LPARAM lParam = NULL;
- int nFirst = pNodePrev->GetLastLine(), nItem = pNodePrev->GetLastItem();
- CListCtrl* pListCtrl = m_pParent->GetListCtrl();
- nResult = pNodePrev->GetLastItem();
- if (pNodeNext == NULL)
- {
- // After the prev node do not exist another node.
- BOOL bEnd = TRUE;
- if (nIF > nFirst)
- {
- SNodeItemsInfo* sThis = pNodePrev;
- pNodePrev = new SNodeItemsInfo(nIF,0, nResult );
- sThis->m_pNextNode = pNodePrev;
- pNodePrev->m_pPrevNode = sThis;
- nFirst = nIF;
- bEnd = FALSE;
- }
- else
- {
- nResult = pNodePrev->m_nItemLB + nIF - pNodePrev->m_nItemLine;
- }
- int i = 0;
- for (i = 0; (lpszItemLB = m_pParent->Label(nFirst + i, lParam)) && (i < nHM); i++)
- {
- pListCtrl->SetItemData(nItem = pListCtrl->InsertItem(nItem, lpszItemLB), lParam);
- m_pParent->LoadRestOfLine(nItem, nFirst + i);
- pNodePrev->m_nCount++;
- nItem++;
- }
- }
- else
- {
- SNodeItemsInfo* pIncreaseNode = pNodeNext->m_pNextNode;
- int nDiff = pNodeNext->m_nItemLine - nFirst;
- ASSERT ( nDiff >= 0 );
- nItem = nResult; // first item that will be inserted
- // {...+..} ___ {...+..}
- if (nDiff <= nHM)
- {
- // The real nHM will be the diference between nHowMany - nDiff
- nHM = nDiff;
- // Try to restrict these node in only one.
- pNodePrev->m_nCount += pNodeNext->m_nCount + nHM;
- pNodePrev->m_pNextNode = pNodeNext->m_pNextNode;
- delete pNodeNext;
- nResult = pNodePrev->m_nItemLB + nIF - pNodePrev->m_nItemLine;
- }
- else
- {
- // nFirst
- // /--- > nHM --
- // {...+..} __+________{......}
- if (nIF < nFirst)
- {
- nResult = pNodePrev->m_nItemLB + nIF - pNodePrev->m_nItemLine;
- nFirst = pNodePrev->GetLastLine();
- pNodePrev->m_nCount += nHM;
- pIncreaseNode = pNodeNext;
- }
- // {......} ______+___ {...+...}
- else
- if (nIF + nHM >= pNodeNext->m_nItemLine)
- {
- nHM = pNodeNext->m_nItemLine - nIF;
- pNodeNext->m_nItemLine = nIF;
- pNodeNext->m_nCount += nHM;
- //pNodeNext->m_nItemLB remains constant
- nItem = pNodeNext->m_nItemLB;
- nFirst = nIF;
- nResult = pNodeNext->m_nItemLB;
- }
- // {......} __+____+___ {......}
- else
- {
- SNodeItemsInfo* sThis = new SNodeItemsInfo(nIF, nHM, nResult );
- sThis->m_pPrevNode = pNodePrev;
- sThis->m_pNextNode = pNodeNext;
- pNodePrev->m_pNextNode = sThis;
- pNodeNext->m_pPrevNode = sThis;
- nFirst = nIF;
- pIncreaseNode = pNodeNext;
- }
- }
- // if some items must insert, do it
- if (nHM > 0)
- {
- for (int i = 0; i < nHM; i++)
- {
- lpszItemLB = m_pParent->Label(nFirst + i, lParam);
- // while pNodePrev and pNodeNext exist !
- ASSERT (lpszItemLB);
- pListCtrl->SetItemData(nItem = pListCtrl->InsertItem(nItem, lpszItemLB), lParam);
- m_pParent->LoadRestOfLine(nItem, nFirst + i);
- nItem++;
- }
- while (pIncreaseNode)
- {
- pIncreaseNode->m_nItemLB += nHM;
- pIncreaseNode = pIncreaseNode->m_pNextNode;
- }
- }
- }
- }
- return nResult;
- }
- // Function name : CQListCtrlCtrl::QSnapLoader::GetItemLine
- // Description : Return the Real line, converts from nItemLB
- // Return type : int
- // Argument : int nItemLB
- int CQListCtrlCtrl::QSnapLoader::GetItemLine(int nItemLB)
- {
- nItemLB = max(0,nItemLB);
- SNodeItemsInfo* pNodeNext = m_pFirstNode;
- while (pNodeNext && ( pNodeNext->m_nItemLB > nItemLB ))
- pNodeNext = pNodeNext->m_pNextNode;
- return pNodeNext->m_nItemLine + nItemLB - pNodeNext->m_nItemLB;
- }