| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481 |
- // DlgTest.cpp : implementation file
- //
- #include "stdafx.h"
- #include "test_list_control.h"
- #include "DlgTest.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // CDlgTest dialog
- CDlgTest::CDlgTest(CWnd* pParent /*=NULL*/)
- : CDialog(CDlgTest::IDD, pParent)
- {
- //{{AFX_DATA_INIT(CDlgTest)
- //}}AFX_DATA_INIT
- // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
- m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
- m_LabelCount=0;
- }
- CDlgTest::~CDlgTest()
- {
- m_arLabels.RemoveAll();
- }
- void CDlgTest::DoDataExchange(CDataExchange* pDX)
- {
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(CDlgTest)
- DDX_Control(pDX, IDC_LIST2, m_List2);
- DDX_Control(pDX, IDC_LIST1, m_List);
- //}}AFX_DATA_MAP
- }
- BEGIN_MESSAGE_MAP(CDlgTest, CDialog)
- //{{AFX_MSG_MAP(CDlgTest)
- ON_WM_PAINT()
- ON_WM_QUERYDRAGICON()
- ON_BN_CLICKED(IDC_ADD, OnAdd)
- ON_NOTIFY(LVN_GETDISPINFO, IDC_LIST1, GetDispInfo)
- ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST1, OnColClick)
- ON_NOTIFY(LVN_ODFINDITEM, IDC_LIST1, OnOdfinditem)
- ON_BN_CLICKED(IDC_ADD2, OnAdd2Normal)
- ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST2, OnColClick2)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // CDlgTest message handlers
- BOOL CDlgTest::OnInitDialog()
- {
- CDialog::OnInitDialog();
- // Set the icon for this dialog. The framework does this automatically
- // when the application's main window is not a dialog
- SetIcon(m_hIcon, TRUE); // Set big icon
- SetIcon(m_hIcon, FALSE); // Set small icon
-
- // Insert the columns.
- CString Header;
- int arColWidth[]={80,100};
- int iNumCols = 2;
- for(int i=0; i<iNumCols; i++)
- {
- Header.LoadString(IDS_LISTCOL+i);
- m_List.InsertColumn(i,Header,LVCFMT_LEFT,arColWidth[i]);
- m_List2.InsertColumn(i,Header,LVCFMT_LEFT,arColWidth[i]);
- }
- // Configure the break icon array.
- m_ImageList.Create(16, 16, ILC_COLOR4, 3, 1);
- m_ImageList.Add(::AfxGetApp()->LoadIcon(IDI_BP_ENABLED));
- m_ImageList.Add(::AfxGetApp()->LoadIcon(IDI_BP_DISABLED));
- m_ImageList.Add(::AfxGetApp()->LoadIcon(IDI_BP_NONE));
- m_List.SetImageList(&m_ImageList, LVSIL_SMALL);
- // Configure the look & feel.
- //const int LVS_EX_LABELTIP = 0x00004000;
- m_List.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_LABELTIP);
- m_List2.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_LABELTIP);
- return TRUE; // return TRUE unless you set the focus to a control
- }
- // If you add a minimize button to your dialog, you will need the code below
- // to draw the icon. For MFC applications using the document/view model,
- // this is automatically done for you by the framework.
- void CDlgTest::OnPaint()
- {
- if (IsIconic())
- {
- CPaintDC dc(this); // device context for painting
- SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
- // Center icon in client rectangle
- int cxIcon = GetSystemMetrics(SM_CXICON);
- int cyIcon = GetSystemMetrics(SM_CYICON);
- CRect rect;
- GetClientRect(&rect);
- int x = (rect.Width() - cxIcon + 1) / 2;
- int y = (rect.Height() - cyIcon + 1) / 2;
- // Draw the icon
- dc.DrawIcon(x, y, m_hIcon);
- }
- else
- {
- CDialog::OnPaint();
- }
- }
- // The system calls this to obtain the cursor to display while the user drags
- // the minimized window.
- HCURSOR CDlgTest::OnQueryDragIcon()
- {
- return (HCURSOR) m_hIcon;
- }
- /**************************************************************************
- Code for virtual list control.
- *************************************************************************/
- void CDlgTest::OnAdd()
- {
- // Fill class data from dialog.
- UpdateData(TRUE);
- // Define a set of pseudo fn names for example.
- char* pszNames[] = {"main","_main","Startup","Fn1","Fn2"};
- CString strText;
- // DWORD start=GetTickCount();
- int i;
-
- ::AfxGetApp()->DoWaitCursor(1);
- // Reset column headers (clear sort order ^).
- LVCOLUMN Col;
- Col.mask=LVCF_TEXT;
- for(i=0; i<2; i++)
- {
- strText.LoadString(IDS_LISTCOL+i);
- Col.pszText=strText.GetBuffer(strText.GetLength()+1);
- Col.cchTextMax=strText.GetLength()+1;
- m_List.SetColumn(i, &Col);
- strText.ReleaseBuffer();
- }
-
- // Clear and reset the label array.
- m_arLabels.RemoveAll();
- m_arLabels.SetSize( 5000, 1000 );
- // Add the 50,000 items.
- CLabelItem Label;
- for(i=0; i<50000; i++)
- {
- Label.m_strText=pszNames[i%5];
- Label.m_Addr=((DWORD)100-(i<<1));
- m_arLabels.SetAtGrow(i, Label);
- }
- m_LabelCount=i;
- // Tell the list box to update itself.
- m_List.SetItemCountEx(m_LabelCount);
- m_List.Invalidate();
- ::AfxGetApp()->DoWaitCursor(0);
- // strText.Format("Time to complete fill was:\n%li ticks", GetTickCount()-start);
- // ::AfxMessageBox(strText);
- }
- void CDlgTest::GetDispInfo(NMHDR* pNMHDR, LRESULT* pResult)
- {
- LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
- LV_ITEM* pItem= &(pDispInfo)->item;
- CLabelItem rLabel = m_arLabels.ElementAt(pItem->iItem);
- if (pItem->mask & LVIF_TEXT) //valid text buffer?
- {
- // then display the appropriate column
- switch(pItem->iSubItem)
- {
- case 0:
- lstrcpy(pItem->pszText, rLabel.m_strText);
- break;
- case 1:
- sprintf(pItem->pszText, "0x%08LX", rLabel.m_Addr);
- break;
- default:
- ASSERT(0);
- break;
- }
- }
- if (pItem->mask & LVIF_IMAGE)
- {
- // then display the appropriate column
- switch(pItem->iSubItem)
- {
- case 0:
- {
- /* long index;
- BOOL iBPState
- BPMgr.Find(rLabel.m_Addr, &index, &iBPState);
- */
- switch(rLabel.m_Addr)
- {
- case 0x00000004:
- pItem->iImage = 0;
- break;
- case 0x00000006:
- pItem->iImage = 1;
- break;
- default:
- pItem->iImage = 2;
- break;
- }
- }
- break;
- default:
- ASSERT(0);
- break;
- }
- }
-
- *pResult = 0;
- }
- // This function is called when the column headers are clicked.
- // (The event occurs on the mouseup event.)
- // Sort the array by the appropriate column contents.
- //
- void CDlgTest::OnColClick(NMHDR* pNMHDR, LRESULT* pResult)
- {
- NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
- LVCOLUMN Col;
- CString ColName;
- // Set text only.
- Col.mask=LVCF_TEXT;
- // Reset the header columns (to indicate the sort order).
- for(int i = 0; i < 2; i++)
- {
- if( i == pNMListView->iSubItem)
- {
- ColName.LoadString(IDS_LISTCOLSEL + i);
- SortByCol(i);
- }
- else
- ColName.LoadString(IDS_LISTCOL + i);
- Col.pszText=ColName.GetBuffer(ColName.GetLength()+1);
- Col.cchTextMax=ColName.GetLength()+1;
- m_List.SetColumn(i, &Col);
- ColName.ReleaseBuffer();
- }
- // Redraw the list.
- m_List.Invalidate();
- *pResult = 0;
- }
- //////////////////////////////////////////////////////////////////////////////
- // Compares two label items by their public data members.
- // Used by qsort algorithm.
- // Must return:
- // < 0 elem1 > elem2
- // 0 elem1 = elem2
- // > 0 elem1 < elem2
- //
- int __cdecl CompareByLabelName(const void *elem1, const void *elem2)
- {
- CLabelItem *p1 = (CLabelItem*)elem1;
- CLabelItem *p2 = (CLabelItem*)elem2;
- return strcmp(p1->m_strText,p2->m_strText);
- }
- int __cdecl CompareByLabelAddr(const void *elem1, const void *elem2)
- {
- CLabelItem *p1 = (CLabelItem*)elem1;
- CLabelItem *p2 = (CLabelItem*)elem2;
- if(p1->m_Addr == p2->m_Addr) return 0;
- if(p1->m_Addr > p2->m_Addr) return 1;
- return -1;
- }
- void CDlgTest::SortByCol(const int ColIndex)
- {
- switch(ColIndex)
- {
- case 0: // Name - this is relatively slow, so show an hourglass.
- ::AfxGetApp()->DoWaitCursor(TRUE);
- qsort( static_cast<void*>(&m_arLabels[0]), m_LabelCount, sizeof(CLabelItem), CompareByLabelName );
- ::AfxGetApp()->DoWaitCursor(FALSE);
- break;
- case 1: // Address.
- qsort( static_cast<void*>(&m_arLabels[0]), m_LabelCount, sizeof(CLabelItem), CompareByLabelAddr );
- break;
- default:
- ASSERT(0);
- break;
- }
- }
- // Handle the quick key event.
- // Move to the next item starting with the pressed key.
- // Searches from the current item + 1 to the end, then starts from 0 to the current item.
- //
- void CDlgTest::OnOdfinditem(NMHDR* pNMHDR, LRESULT* pResult)
- {
- NMLVFINDITEM* pFindInfo = (NMLVFINDITEM*)pNMHDR;
- LVFINDINFO FindItem = pFindInfo->lvfi;
- int i;
- if(FindItem.flags & LVFI_STRING)
- {
- TCHAR chKeyL = FindItem.psz[0];
- TCHAR chKeyH = _toupper(FindItem.psz[0]);;
- // Search to end.
- for( i = pFindInfo->iStart; i < m_LabelCount; i++ )
- {
- if( ( chKeyL == m_arLabels[i].m_strText[0] )
- || ( chKeyH == m_arLabels[i].m_strText[0] )
- )
- {
- *pResult = i;
- return;
- }
- }
- // Search from 0 to start.
- for( i = 0; i < pFindInfo->iStart; i++ )
- {
- if( ( chKeyL == m_arLabels[i].m_strText[0] )
- || ( chKeyH == m_arLabels[i].m_strText[0] )
- )
- {
- *pResult = i;
- return;
- }
- }
- }
- *pResult = -1; // Default action.
- }
- /**************************************************************************
- Code for normal list control.
- *************************************************************************/
- void CDlgTest::OnAdd2Normal()
- {
- // Fill class data from dialog.
- UpdateData(TRUE);
- // Define a set of pseudo fn names for example.
- char* pszNames[] = {"main","_main","Startup","Fn1","Fn2"};
- CString strText;
- // DWORD start=GetTickCount();
- int i;
- ::AfxGetApp()->DoWaitCursor(1);
- // Reset column headers (clear sort order ^).
- LVCOLUMN Col;
- Col.mask=LVCF_TEXT;
- for(i=0; i<2; i++)
- {
- strText.LoadString(IDS_LISTCOL+i);
- Col.pszText=strText.GetBuffer(strText.GetLength()+1);
- Col.cchTextMax=strText.GetLength()+1;
- m_List.SetColumn(i, &Col);
- strText.ReleaseBuffer();
- }
- // Clear and reset the list control content.
- m_List2.DeleteAllItems();
- // Add the 50,000 items.
- CString strAddr;
- int index;
- for(i=0; i<50000; i++)
- {
- index=m_List2.InsertItem(i, pszNames[i%5]);
- if(-1!=index)
- {
- strAddr.Format("0x%08lX", 100-(i<<1) );
- m_List2.SetItemText(index, 1, strAddr);
- m_List2.SetItemData(index, index); // Needed for sort algorithm.
- }
- }
- ::AfxGetApp()->DoWaitCursor(0);
- // strText.Format("Time to complete fill was:\n%li ticks", GetTickCount()-start);
- // ::AfxMessageBox(strText);
- }
- void CDlgTest::OnColClick2(NMHDR* pNMHDR, LRESULT* pResult)
- {
- NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
- LVCOLUMN Col;
- CString ColName;
- // Set text only.
- Col.mask=LVCF_TEXT;
- // Reset the header columns (to indicate the sort order).
- for(int i = 0; i < 2; i++)
- {
- if( i == pNMListView->iSubItem)
- {
- ColName.LoadString(IDS_LISTCOLSEL + i);
- Sort2ByCol(i);
- }
- else
- ColName.LoadString(IDS_LISTCOL + i);
- Col.pszText=ColName.GetBuffer(ColName.GetLength()+1);
- Col.cchTextMax=ColName.GetLength()+1;
- m_List2.SetColumn(i, &Col);
- ColName.ReleaseBuffer();
- }
- // Redraw the list.
- m_List2.Invalidate();
-
- *pResult = 0;
- }
- int CALLBACK Compare2ByLabelName(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
- {
- CListCtrl* pListCtrl = (CListCtrl*) lParamSort;
- CString strItem1 = pListCtrl->GetItemText(lParam1, 0);
- CString strItem2 = pListCtrl->GetItemText(lParam2, 0);
- return strcmp(strItem2, strItem1);
- }
- int CALLBACK Compare2ByLabelAddr(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
- {
- CListCtrl* pListCtrl = (CListCtrl*) lParamSort;
- DWORD Addr1 = (DWORD)strtoul(pListCtrl->GetItemText(lParam1, 1),NULL,16);
- DWORD Addr2 = (DWORD)strtoul(pListCtrl->GetItemText(lParam2, 1),NULL,16);
- if(Addr1 == Addr2) return 0;
- if(Addr1 > Addr2) return 1;
- return -1;
- }
- void CDlgTest::Sort2ByCol(const int ColIndex)
- {
- switch(ColIndex)
- {
- case 0: // Name - this is relatively slow, so show an hourglass.
- ::AfxGetApp()->DoWaitCursor(TRUE);
- m_List2.SortItems( Compare2ByLabelName, (DWORD)&m_List2 );
- ::AfxGetApp()->DoWaitCursor(FALSE);
- break;
- case 1: // Address.
- ::AfxGetApp()->DoWaitCursor(TRUE);
- m_List2.SortItems( Compare2ByLabelAddr, (DWORD)&m_List2 );
- ::AfxGetApp()->DoWaitCursor(FALSE);
- break;
- default:
- ASSERT(0);
- break;
- }
- }
|