[BCB] Windows listview sorteren

Pagina: 1
Acties:

  • reddevil
  • Registratie: Februari 2001
  • Laatst online: 06-10 14:25
In borland c++ builder 2006:
Ik ben bezig met een listview (van windows, dus niet de tlistview van borland/vcl) te implementeren. Dit doe ik omdat de TListView van VCL veels te langzaam is bij grotere aantallen rijen. Nu plaats ik een listview op een TListView, dit doe ik zodat ik via designer de grootte en positie van de listview kan aangeven.

De listview is als volgt gecreeerd:
C++:
1
2
3
4
5
6
7
8
9
10
DWORD dwStyle;
dwStyle = LVS_REPORT | LVS_SINGLESEL | 
                WS_VISIBLE | WS_CHILD | WS_VSCROLL;

hAvailableList = CreateWindowEx(WS_EX_CLIENTEDGE, "SysListView32", "", dwStyle,
            0, 0,
            lvAvailable->Width,
            lvAvailable->Height,
            lvAvailable->Handle, NULL,
            GetModuleHandle(NULL), NULL);


hAvailableList is een handle naar de nieuwe listview en lvAvailable is de TListView waar de list view overheen gelegd moet worden.

Om te zorgen dat ik van de listview messages kan afvangen heb ik de volgende code toegevoegd na de CreateWindowEx:
C++:
1
2
lvWndProc = (WNDPROC)GetWindowLong(hAvailableList, GWL_WNDPROC);
SetWindowLong(hAvailableList, GWL_WNDPROC, (long)ListViewProc);

lvWndProc is ook een handle.

Daarna voeg ik nog 2 kolommen toe, wat geen probleem oplevert:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
LVCOLUMN lvc = { 0 };
lvc.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH  | LVCF_FMT;
lvc.fmt  = LVCFMT_LEFT;
lvc.iSubItem = 0;
lvc.cx       = 50;
lvc.pszText  = TEXT("Record");
ListView_InsertColumn(hAvailableList, 0, &lvc);

lvc.iSubItem = 1;
lvc.cx       = 100;
lvc.pszText  = TEXT("Name");
ListView_InsertColumn(hAvailableList, 1, &lvc);


So far so good...

Het toevoegen van listitems is ook geen probleem:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    char szText[64];
    int nItem, nSubItem;
    LVITEM lvi;

    for (nItem = 0; nItem < 500; ++nItem)
    {
        sprintf(szText, "Item %d", nItem);
        lvi.mask = LVIF_TEXT | LVIF_PARAM;
        lvi.iItem = nItem;
        lvi.iSubItem = 0;
        lvi.pszText = szText;
        lvi.cchTextMax = strlen(szText);
        lvi.lParam = nItem;
        ListView_InsertItem(hAvailableList, &lvi);

        // set up subitems
        for (nSubItem = 1; nSubItem < 2; ++nSubItem)
        {
            sprintf(szText, "Item %d.%d", nItem, nSubItem);
            lvi.mask = LVIF_TEXT;
            lvi.iItem = nItem;
            lvi.iSubItem = nSubItem;
            lvi.pszText = szText;
            lvi.cchTextMax = strlen(szText);
            ListView_SetItem(hAvailableList, &lvi);
        }
    }


Nu wil ik de messages afvangen door een functie ListViewProc te maken:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
BOOL CALLBACK ListViewProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_NOTIFY:
        {
            switch (((LPNMHDR) lParam)->code)
            {
                case LVN_COLUMNCLICK:
                {
                    OnColumnClick((LPNMLISTVIEW)lParam);
                } break;
            }
        }
    }

    return CallWindowProc((int(__stdcall*)())lvWndProc, hWnd, uMsg, wParam, lParam);
}


Dit stuk werkt dus niet :( De OnColumnClick functie wordt geeneens aangeroepen (niet echt belangrijk wat daar in staat, want als ik maar eenmaal in die functie kan komen is het wel ok).
Ik heb half google rondgezocht, maar alles duidt erop dat bovenstaand moet werken, maar ik heb het idee dat de goede message niet doorkomt.
Een tweetal echte samples die ik vond hadden een DialogProc, welke in de WinMain was gezet, maar dat wil ik niet zo. Iemand die kan helpen?

Er zal wat overbodige code mogelijk hier en daar staan en da's niet zo erg... finetunen/optimaliseren komt wel nadat alles werkt.

  • Domokoen
  • Registratie: Januari 2003
  • Laatst online: 03-11 22:45
Roep je wel BeginUpdate en EndUpdate aan als je de "originele" TListView van BCB gebruikt? Deze zorgt ervoor dat het window niet opnieuw getekend wordt terwijl je items aan het toevoegen/verwijderen bent. Want ik vraag me af of de native Windows list control echt zoveel beter is... die van BCB is een wrapper daar omheen.

  • reddevil
  • Registratie: Februari 2001
  • Laatst online: 06-10 14:25
Klein testprogramma voor toevoegen van 10000 rijen (2 kolommen):

Borland TListView:
- zonder begin/endupdate: 12 seconden
- met begin/endupdate: 9 seconden

Windows ListView: 2 seconden

En nu ik zover ben wil ik weten wat ik verkeerd doe ook :)

  • schoene
  • Registratie: Maart 2003
  • Laatst online: 01-12 16:07
volgende code in BCB6:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
TDateTime t = Now ();

for (int i=0; i < 10000; ++i)
   {
   TListItem *item = ListView1->Items->Add();
   item->Caption = "col1";
   item-> SubItems->Add("col2");
   }


Application->ProcessMessages ();

TDateTime t2 = Now ();
ShowMessage ( (int) ((double)(t2-t)*24.0*60.0*60.0*1000.0));


ik krijg als uitvoer 2200 ms. Of zie ik het verkeerd?

  • reddevil
  • Registratie: Februari 2001
  • Laatst online: 06-10 14:25
En ik krijg daar 9265ms met een nieuw, leeg vcl app. project.

Dus op dit moment zit ik met 2 problemen ;)
1. Waarom werkt m'n windows listview code niet
2. Waarom is ie bij mij zo traag in bcb!

Ik zie dat een virtual listview veel sneller is. Het verschil is dat je geen data object aan een listitem koppelt, maar bij bovenstaande code wordt dat toch al niet gedaan of moet je ergens een instelling zetten van de listview dat ie 'virtual mode' gaat ofzo?

Update: OwnerData... ik zal even ondertussen hier mee testen
Update2: Ok met ownerdata kan ik binnen 1,5s 100k records toevoegen en tonen, dat gaat wel lukken. Maar dan nog m'n probleem bovenaan, waarom kan ik zo niet sorteren?

[ Voor 144% gewijzigd door reddevil op 22-05-2007 12:21 ]