ListControl(ListView)



  • Hallo!
    Ich arbeite gerade an einem klienem Projekt und würde gerne wissen wie man eine ListView in WIN32(C) befüllen kann??

    MFG!



  • 2.1 Hinzufügen von Columns

    Um ein Column zu einem ListView-Control hinzuzufügen, muss die gefüllte Struktur LV_COLUMN via SendMessage () bzw. ListView_InsertColumn () an das Control gesendet werden. Ich werde hier nur mit der 2. Variante arbeiten, da diese die kürzere ist und zumal diese Variante intern auch nur mit SendMessage () arbeitet. LV_COLUMN ist in "commctrl.h" wie folgt definiert:

    typedef struct tagLVCOLUMNA
    {
        UINT mask;
        int fmt;
        int cx;
        LPSTR pszText;
        int cchTextMax;
        int iSubItem;
    #if (_WIN32_IE >= 0x0300)
        int iImage;
        int iOrder;
    #endif
    } LVCOLUMNA, FAR* LPLVCOLUMNA;
    

    In diesem Zusammenhang werde ich nur die ersten 6 Elemente benutzen. Nachfolgend die Beschreibung der Elemente:

    • mask: definiert, welche Elemente benutzt werden sollen über: LVCF_FMT, LVCF_WIDTH, LVCF_TEXT, LVCF_SUBITEM, LVCF_IMAGE, LVCF_ORDER
    • fmt: Formatierungen für das Column: LVCFMT_LEFT, LVCFMT_RIGHT, LVCFMT_CENTER, LVCFMT_JUSTIFYMASK, LVCFMT_IMAGE, LVCFMT_BITMAP_ON_RIGHT, LVCFMT_COL_HAS_IMAGES (benötigt, wenn LVCF_FMT in mask definiert ist)
    • cx: Breite des Columns (benötigt, wenn LVCF_WIDTH in mask definiert ist)
    • pszText: Text/Name des Columns (benötigt, wenn LVCF_TEXT in mask definiert ist)
    • cchTextMax: Maximallänge von pszText (benötigt, wenn LVCF_TEXT in mask definiert ist)
    • iSubItem: Nummer des Columns (benötigt, wenn LVCF_SUBITEM in mask definiert ist)
    • iImage und iOrder sind hier außen vor gelassen

    Nachdem das alles geklärt ist, nun eine Funktion, in der das unter 2.1 beschriebene zusammen getragen ist:

    bool InsertListViewColumn (HWND hListView,
                               LPTSTR lpColumnName,
                               int iWidth,
                               int iSubItem,
                               DWORD dwStyle = NULL)
    {
        int iStatus;
    	LV_COLUMN lvc;
    
    	lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
    	lvc.fmt = LVCFMT_LEFT | dwStyle;
    	lvc.cx = iWidth;
    	lvc.pszText = lpColumnName;
    	lvc.cchTextMax = 100;
    	lvc.iSubItem = iSubItem;
    
    	iStatus = ListView_InsertColumn (hListView, iSubItem, &lvc)
    
        return (iStatus != -1);
    }
    

    Diese Funktion kann an einer beliebigen Position im Code aufgerufen werden, vorausgesetzt das ListView-Control wurde bereits erstellt. Wenn sie erfolgreich war, liefert sie true zurück, ansonsten false. Eingesetzt wird die Funktion zum Beispiel so:

    case WM_CREATE:
        INITCOMMONCONTROLSEX icc;
        icc.dwSize = sizeof (INITCOMMONCONTROLSEX);
        icc.dwICC  = ICC_LISTVIEW_CLASSES;
    
        InitCommonControlsEx (&icc);
        hListView = CreateWindow (WC_LISTVIEW, "",
                                  WS_CHILD | WS_VISIBLE | LVS_REPORT,
                                  5, 5, 300, 300,
                                  hWnd, (HMENU) LISTVIEW,
                                  g_hInst, NULL);
    
        InsertListViewColumn (hListView, "1. Spalte", 150, 0);
        InsertListViewColumn (hListView, "2. Spalte", 150, 0, LVCFMT_CENTER);
    return 0;
    

    Das war auch schon alles. Es ist also nicht ganz so schwer, wie man am Anfang denkt.

    2.2 Hinzufügen von Einträgen

    Das Hinzufügen von Einträgen ist ähnlich. Um ein Eintrag in ein ListView-Control unter eine Spalte zu bekommen, muss man mit SendMessage () bzw. mit ListView_InsertItem () eine gefüllte LV_ITEM-Struktur an das Control senden. Wie auch bei 2.1, hier ersteinmal die Strukur:

    typedef struct tagLVITEMA
    {
        UINT mask;
        int iItem;
        int iSubItem;
        UINT state;
        UINT stateMask;
        LPSTR pszText;
        int cchTextMax;
        int iImage;
        LPARAM lParam;
    #if (_WIN32_IE >= 0x0300)
        int iIndent;
    #endif
    } LVITEMA, FAR* LPLVITEMA;
    

    Und hier die Erklärung der Elemente:

    • mask: definiert, welche Elemente benutzt werden sollen über: LVIF_TEXT, LVIF_IMAGE,
      LVIF_PARAM(, LVIF_STATE)
    • iItem: Zeile, in der der Eintrag eingefügt werden soll
    • iSubItem: Spalte, in die der Eintrag eingefügt werden soll
    • pszText: Eintrag (benötigt, wenn LVIF_TEXT in mask definiert ist)
    • cchTextMax: Maximallänge von pszText (benötigt, wenn LVIF_TEXT in mask definiert ist)
    • lParam: Parameter, um den Eintrag zu identifizieren, z.B für das Sortieren (benötigt, wenn LVIF_PARAM in mask definiert ist)
    • iImage, state und stateMask sind hier außen vor gelassen

    Diese Struktur muss nur noch via ListView_InsertItem () an das Control gesendet werden, und schon ist ein Eintrag drin.
    Nun aber zu einem Problem: ListView_InsertItem () kann nur für die erste (!) Spalte benutzt werden. Für die anderen Columns muss ListView_SetItem verwendet werden. Nachdem auch das beachtet ist, kann man sich daraus ja wieder eine Funktion basteln, um die Geschichte zu erleichtern:

    bool InsertListViewEntry (HWND hListView,
                              LPTSTR lpEntryValue,
                              int iRowID,
                              int iColID)
    {
        int iStatus;
    	LV_ITEM lvi;
    
    	lvi.mask = LVIF_TEXT;
    	lvi.iItem = iRowID;
        lvi.iSubItem = iColID;
        lvi.pszText = lpEntryValue;
    	lvc.cchTextMax = MAX_PATH;
    
    	if (iColID == 0)
    		iStatus = ListView_InsertItem (hListView, &lvi);
    	else
    		iStatus = ListView_SetItem (hListView, &lvi);
    
        return (iStatus != -1 || iStatus != false);
    }
    

    Auch diese Funktion gibt bei einem Misserfolg false zurück und andernfalls true.
    Hier das Beispiel, wie diese Funktion zusammen mit InsertListViewColumn () funktionieren kann:

    case WM_CREATE:
        INITCOMMONCONTROLSEX icc;
        icc.dwSize = sizeof (INITCOMMONCONTROLSEX);
        icc.dwICC  = ICC_LISTVIEW_CLASSES;
    
        InitCommonControlsEx (&icc);
        hListView = CreateWindow (WC_LISTVIEW, "",
                                  WS_CHILD | WS_VISIBLE | LVS_REPORT,
                                  5, 5, 300, 300,
                                  hWnd, (HMENU) LISTVIEW,
                                  g_hInst, NULL);
    
        InsertListViewColumn (hListView, "1. Spalte", 150, 0);
        InsertListViewColumn (hListView, "2. Spalte", 150, 0, LVCFMT_CENTER);
    
        InsertListViewEntry (hListView, "Spalte 0, Zeile 0", 0, 0);
        InsertListViewEntry (hListView, "Spalte 1, Zeile 0", 0, 1);
    
        InsertListViewEntry (hListView, "Spalte 0, Zeile 1", 1, 0);
        InsertListViewEntry (hListView, "Spalte 1, Zeile 1", 1, 1);
    return 0;
    

    So, das war auch schon alles zu den Einträgen.

    Das habe ich mal aus meinem Artikel einfach so kopiert...
    Der wird auch irgendwann mal veröffentlicht, wenn ich ihn endlich mal fertig kriege...
    Abgesehen davon, benutze mal die SuFu das habe ich und andere nicht das erste mal erklärt bw. gepostet.



  • Also als erstes Danke für die schnelle Antwort!

    Mein Problem ist:
    Ich habe mit dem RC-Editor eine ListControl erstellt!Und jetzt will ich die ListView mit Elementen befüllen!
    Mit der oben beschriebenen Variante funktioniert es nicht!
    MFG


  • Mod

    Was funktioniert nicht, und wie hast Du es gemacht? Zeige einfach mal etwas Code.



  • Als erstes schreit er das er diesen Befehl INITCOMMONCONTROLSEX nicht kennt..


  • Mod

    Dann hast Du vermutlich ein altes SDK. Verwende InitCommonControls!



  • Komisch aber diesen Befehl kennt er auch nicht...Wäre nett wenn jemand eine BSP Applikation posten könnte...



  • hast du den header commctrl.h eingebunden?

    EDIT: INITCOMMONCONTROLSEX ist kein Befehl sondern ein Strukt 😉

    probiers mal anstatt damit hiermit:

    case WM_CREATE: 
        InitCommonControls (); 
        hListView = CreateWindow (WC_LISTVIEW, "", 
                                  WS_CHILD | WS_VISIBLE | LVS_REPORT, 
                                  5, 5, 300, 300, 
                                  hWnd, (HMENU) LISTVIEW, 
                                  g_hInst, NULL); 
    
        InsertListViewColumn (hListView, "1. Spalte", 150, 0); 
        InsertListViewColumn (hListView, "2. Spalte", 150, 0, LVCFMT_CENTER); 
    
        InsertListViewEntry (hListView, "Spalte 0, Zeile 0", 0, 0); 
        InsertListViewEntry (hListView, "Spalte 1, Zeile 0", 0, 1); 
    
        InsertListViewEntry (hListView, "Spalte 0, Zeile 1", 1, 0); 
        InsertListViewEntry (hListView, "Spalte 1, Zeile 1", 1, 1); 
    return 0;
    


  • Hmm BitWax, da du dich so gut mit Listviews auskennst. Weißt du zufällig auch wie ich ein Bild in einen Eintrag an einer anderen Spalte als der Ersten bekomme? Mit einer Image_List habe ich es schon versucht, allerdings kann ich ein Bild nur in der jeweils ersten Spalte anzeigen lassen...



  • hmm ne...also ich hab das auch noch nicht ausprobiert und gesehen in nem anderen prog auch nicht...


  • Mod

    Man muss den Stil LVS_EX_SUBITEMIMAGES verwenden und das Image mit LVM_SETITEM setzen.



  • Martin Richter schrieb:

    Man muss den Stil LVS_EX_SUBITEMIMAGES verwenden und das Image mit LVM_SETITEM setzen.

    Nein! Das war es und ich suche schon ewig (unter anderem mit extra Thread hier im Forum) nach einer Lösung. Man muss nur genug oft fragen, irgendwann kommt einer von Microsoft und verrät die Lösung 🙂 Danke auf jeden Fall.


  • Mod

    PS: Ich bin nicht von Microsoft... 🕶


Log in to reply