[A] ListView-Controls im Report-Modus via WinAPI



  • Vorwort

    Ich möchte mit diesem Beitrag die ListView-Controls jedem ein bisschen näher bringen. Ich werde ersteinmal nur die Erstellung von ListViews im Report-Modus behandeln.

    Einteilung

    • 1. Erstellung
    • 2. Konfiguration
    • 2.1 Hinzufügen von Columns
    • 2.2 Hinzufügen von Einträgen
    • 2.3 Farben
    • 2.3.1 einfache Text- und Hintergrundfarbe
    • 2.3.2 erweiterte Text- und Hintergrundfarbe
    • 2.4 Größen und Sortierung
    • 2.4.1 Größenänderung von Columns verhindern
    • 2.4.2 Sortierung nach Columns

    --------------------------------------------------------------------------

    1. Erstellung

    Da ein ListView-Control kein Standard-Control aus der "windows.h" ist, muss vorher noch der passende Header inkludiert werden. In diesem Fall ist es "commctrl.h". Diese Datei enthält die Definitionen von dem ListView-Control. Außerdem beinhaltet "commctrl.h" noch TreeView-, Trackbar-, Progress-, Tab-, UpDown- und einige weitere Controls. Um diese Controls nutzen zu können, muss noch die Funktion InitCommonControlsEx () aufgerufen werden. Die Funktion stellt sicher, dass die benötigte Programmbibliothek für die Controls geladen wurde und benötigt als Paramter einen Zeiger der Strukur INITCOMMONCONTROLSEX. So ist die Strukur in "commctrl.h" definiert:

    typedef struct tagINITCOMMONCONTROLSEX {
        DWORD dwSize;             // size of this structure
        DWORD dwICC;              // flags indicating which classes to be initialized
    } INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
    

    Hier die Erklärung der Elemente:

    • dwSize: Größe der Struktur
    • dwICC: Flags, die angeben, welche Controls alle initialisiert werden sollen; möglich sind:
      ICC_LISTVIEW_CLASSES, ICC_TREEVIEW_CLASSES, ICC_BAR_CLASSES, ICC_TAB_CLASSES, ICC_UPDOWN_CLASS, ICC_PROGRESS_CLASS, ICC_HOTKEY_CLASS, ICC_ANIMATE_CLASS, ICC_WIN95_CLASSES, ICC_DATE_CLASSES, ICC_USEREX_CLASSES, ICC_COOL_CLASSES, ICC_INTERNET_CLASSES, ICC_PAGESCROLLER_CLASS und ICC_NATIVEFNTCTL_CLASS

    Für ListView-Controls wird nur das erste Flag aus der Liste benötigt. Nun zum Einbinden von ListView-Controls in ein Programm. Das Control wird unter der Fenster-Message WM_CREATE wie ein Standard-Control erstellt:

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

    Als Name der Fensterklasse wird WC_LISTVIEW angegeben. Ansonsten unterscheidet sich die restliche CreateWindow ()-Funktion nicht, von z.B. der eines Buttons. Vor dem ListView-Control wird die oben beschriebene Funktion InitCommonControlsEx () aufgerufen, damit nichts schief geht. Diese Funktion kann auch bereits in der WinMain aufgerufen werden. Damit wurde ein ListView-Control erstellt, wie es auch z.B. in der Symbolansicht des Explorers verwendet wird. Um ein ListView-Control im Report-Modus zu erstellen, muss noch LVS_REPORT als Style mit angegeben werden. Fertig ist das ListView-Control im Report-Modus!

    2. Konfiguration

    Nachdem das ListView-Control erfolgreich erstellt wurde, beschäftige ich mich jetzt mit der Konfiguration dessen. D.h.: Columns, Einträge, Farben, Größen.

    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.

    2.3 Farben

    In diesem Bereich beschäftige ich mich mit der Farbgebung von ListView-Controls.

    2.3.1 einfache Text- und Hintergrundfarbe

    Dieser Teil ist sehr schnell abgehandelt. Um die Hintergrundfarbe von einem ListView-Control zu ändern, benutzt man das Makro ListView_SetBkColor (), für die Texthintergrundfarbe das Makro ListView_SetTextBkColor () und für die Textfarbe das Makro ListView_SetTextColor (). Ein schwarzes ListView-Control mit weißen Text und schwarzen Texthintergrund könnte also so aussehen:

    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);
    
    	ListView_SetBkColor (hListView, RGB (0, 0, 0));
    	ListView_SetTextBkColor (hListView, RGB (0, 0, 0));
    	ListView_SetTextColor (hListView, RGB (255, 255, 255));
    
        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;
    

    2.3.2 erweiterte Text- und Hintergrundfarbe

    Um die Zeilen z.B. zweifarbig im Wechsel zu färben, muss man selbst zeichnen. Um das zu können, muss das ListView-Control beim Erstellen noch LVS_OWNERDRAWFIXED als Style hinzubekommen. Danach wird die vordefinierte Zeichenoperation ausgesetzt und man kann über WM_DRAWITEM selber zeichnen. WM_DRAWITEM bekommt über den lParam-Wert eine Struktur, in der alle wichtigen Daten (Größe, Device Kontext, ID, etc.) über das zu zeichnende Element enthalten sind. Diese Struktur nennt sich DRAWITEMSTRUCT, allerdings werde ich nicht näher auf die Elemente eingehen. Damit man nun zeichnen kann, muss man erstmal wissen, ob das zu zeichnende Objekt auch wirklich das ListView-Control ist. Das findet man über das in der Struktur enthaltene Element hwndItem heraus. Wenn es das Control ist, muss man überprüfen, ob das Item irgendeinen Status hat, also ob es zum Beispiel selektiert ist. Weil wenn, dann soll es ja eine andere Farbe bekommen. Das passende Element dafür ist itemState und der Wert ist ODS_SELECTED, falls es selektiert ist. Wenn das Item nicht diesen Status hat, soll es auch nicht die Farbe bekommen, als wäre es selektiert. Im Element itemID von DRAWITEMSTRUCT steht die ID des Items. Wenn es eine gerade Zahl ist, soll das Item eine andere Farbe bekommen, als wenn die Zahl gerade ist. Mit den Farben kann man nun einen Brush erstellen und diesen über FillRect () auf das Rechteck des Items anwenden. der Device Context ist in hDC gespeichert und das Rechteck in rcItem. Anschließend nicht vergessen den Brush über DeleteObject zu löschen. Fertig. Aber Moment! Wo bleibt der Text? Der muss ja schließlich auch irgendwie gezeichnet werden! Also ran an die Arbeit!
    Zuerst wird ein Puffer angelegt, der den Text aufnehmen kann. Anschließend wird das Makro ListView_GetItemText () dazu verwendet, über die ID itemID den Text in den Puffer zu schreiben. Über SetTextBkColor () und SetTextColor () kann man noch die Farben für den Hintergrund des Textes und die Farbe für den Text ändern. Alles was jetzt noch fehlt, ist den Text auf den Device Context zu pappen. Über TextOut () ist auch das schnell erledigt und fertig ist das selbstgezeichnete ListView-Control!
    Hier nocheinmal ein Beispiel:

    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 | LVS_OWNERDRAWFIXED,
                                  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;
    
    case WM_DRAWITEM:
        dis = (DRAWITEMSTRUCT*) lParam;
        if (dis->hwndItem == hListView)
        {
            COLORREF bgColor;
    
            if (dis->itemState & ODS_SELECTED)
                bgColor = RGB (200, 240, 200);
            else
            {
                if (dis->itemID % 2 == 0)
                    bgColor = RGB (245, 245, 245);
                else
                    bgColor = RGB (230, 230, 250);
            }
    
            HBRUSH hbr = CreateSolidBrush (bgColor);
            FillRect (dis->hDC, &dis->rcItem, hbr);
    
            DeleteObject (hbr);
    
            char buf[100];
            ListView_GetItemText (hClientListView, dis->itemID, 0, buf, 100);
    
            TextOut (dis->hDC, dis->rcItem.left, dis->rcItem.top, buf, strlen (buf));
        }
    return 0;
    

    Viel Text, viel Erklärung, wenig Code, viel Ergebnis.

    2.4 Größen und Sortierung

    2.4.1 Größenänderung von Columns verhindern

    Dieser Teil ist auch wieder schnell abgehandelt. Um zu verhindern, dass der User die Columns kleiner bzw. größer machen kann, muss nur die Message HDN_ITEMCHANGING unter WM_NOTIFY abgefangen werden. Diese Message wird immer dann gesendet, wenn eine Änderung an einer Eigenschaft eines Headers bzw. Columns vorgenommen werden soll. In dieser Message überprüft man dann noch, ob es sich um ein Column aus dem ListView-Control handelt und gibt dann einfach
    1 zurück, falls ja.

    case WM_NOTIFY:
        switch (((LPNMHDR) lParam)->code)
        {
            case HDN_ITEMCHANGING:
                #define phn     ((HD_NOTIFY FAR *) lParam)
                if ((int) phn->iItem == 0)
                {
                    if ((int) phn->hdr.hwndFrom == SendMessage (hClientListView, LVM_GETHEADER, 0, 0))
                        return 1;
                }
                #undef phn
            break;
        }
    return 0;
    

    So einfach kann das sein. Nun der vorerst letzte Teil.

    2.4.2 Sortierung nach Columns

    Um die Einträge bei einen Klick auf ein Column zu sortieren, wird auch hier wieder WM_NOTIFY benötigt. Diesmal ist allerdings LVN_COLUMNCLICK verantwortlich. Das Makro ListView_SortItem () dient zum Sortieren von Einträgen. Allerdings benötigt es eine Funktion, in der die Regel, nach der sortiert werden soll, aufgeführt wird. Und hier kommt das vorhin erwähnte Element lParam aus der LV_ITEM-Struktur zum Einsatz. Das Makro übergibt an die Sortier-Funktion nähmlich nur 3 Werte: 2 lParam-Werte von Einträgen und einen lParam Wert, der über das Makro überliefert wird. Natürlich könnte auch hier wieder SendMessage () benutzt werden. Diese Sortier-Funktion übernimmt und verarbeitet dann die Werte. Hier ein Beispiel:

    LRESULT CALLBACK ListViewSorting (LPARAM, LPARAM, LPARAM);
    .
    .
    .
    case WM_NOTIFY:
        switch (((LPNMHDR) lParam)->code)
        {
            case LVN_COLUMNCLICK:
                #define pnm ((NM_LISTVIEW *) lParam)
                ListView_SortItems (pnm->hdr.hwndFrom, ListViewSorting, (LPARAM) (pnm->iSubItem));
                #undef pnm
            break;
        }
    return 0;
    .
    .
    .
    LRESULT CALLBACK ListViewSorting (LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
    {
        UNREFERENCED_PARAMETER (lParamSort);
        if(lParam1 < lParam2)
            return -1;
        else if(lParam1 > lParam2)
            return 1;
        else
            return 0;
    }
    

    Das Makro UNREFERENCED_PARAMTER () dient nur dazu, die Warnung vom Compiler zu unterdrücken, dass lParamSort nicht benutzt wird.

    Das war es vorerst von ListView-Controls.

    Ich bedanke mich für Ihre Aufmerksamkeit, hoffentlich bis zum nächsten Mal!
    BitWax



  • Wow, meine Hochachtung! 👍 Alles nötige abgedeckt 🙂

    Winzig kleine Sächelchen (Rechtschreibfehler wolltest du selber suchen, aber vielleicht hättest du ihn ja übersehen):
    "WM_DRAWITEM bekommt über den lParam-Wert ein Strukt" <- Ich würde eher Struct schreiben
    Zum Rückgabewert von ListView_InsertItem/-SetItem: InsertItem gibt Index bzw -1 zurück, SetItem TRUE oder FALSE.

    Evtl einen funktionierenden Beispiel-Code ganz am Schluss? [Habt ihr Recht!)

    Wenn das alles korrigiert ist, kann der Beitrag hier auch weg (Ästhetik und so), muss dann ein fleißiger Mod machen 🤡

    Aber so in allem: Wirklich großartig, vor allem da du das so schnell (quasi sofort) umgesetzt hast, wird ja doch was aus der Enhanced-FAQ 🙂 👍



  • Dito. Daumenschrauben hoch 👍

    Aber wozu noch ganze Dateien einbinden? Sollte doch imho soweit
    alles mehr als verständlich sein.



  • So, habe das jetzt überarbeitet. Der Code übertritt jetzt auch nicht mehr den Rahmen.

    @Badestrand: mit Strukt habe ich jetzt ins Deutsche übersetzt, also die Strukur und nicht der Strukt.
    Und zu dem Vorschlag mit dem Code: Ich glaube das würde den Rahmen sprengen, also gebe ich da Quam recht. Und wenn dann würde sich sowas wie ein Datei-Loader mit einem TreeView eher anbieten.

    Aber danke für das Lob und die konstruktive Kritik. Ich bin natürlich immernoch für weitere Vorschläge zu haben.

    Danke auch für das Lob, aus dem Forentechnik-Thread



  • Ja echt gut 👍
    Das einzige was mir beim überfliegen aufgefallen ist, benutzte lieber InitCommonControlsEx();

    schirrmie



  • Wenn ich mich nicht irre, dann macht InitCommonControlEx doch auch nichts anderes, als je nach Angabe ein paar defines à la "#define NOHEADER" o.ä. zu setzen, oder? Also das unnötige definieren von Funktionen und Makros zu verhindern.
    Ok, kann ich ja machen, damit reiß ich mir ja kein Bein aus!



  • So, eigentlich muss ja nur das Layout angepasst werden, oder?
    🙂



  • gerade geschehen 😉



  • Super. 👍

    Wenn du dann inhaltlich nichts mehr ändern willst (was ich vermute), kannst du den Titel auf [T] statt [A] ändern. 🙂



  • Gleich zu Beginn in dem "Abstract" wäre es schön, wenn Du direkt erwähnen würdest, dass es nur um das entsprechende Windows-Control geht. Das war im WinAPI-Forum natürlich unnötig. Aber ich denke es ist schöner den Leser nicht anhand dessen dass Du von der windows.h redest merken zu lassen, dass es hier konkret um die ListControls aus Windows geht. 😉



  • Oder der Titel wird geändert auf
    WinAPI: ListView-Controls im Report-Modus
    oder so ähnlich. Dass man es eben gleich im Titel sieht. Ist bei den anderen Artikeln ja auch.



  • Habe jetzt mal den Titel geändert. Ich glaube der ist so in Ordnung.



  • Nimm vieleicht noch die Zeilenumbrüche raus.

    Sollten bei den list tags nicht auch noch Bullets sein? 😕

    Test

    • 1
    • 2

    EDIT : BitWax du hast die List Tags falsch eingesetzt. Das geht folgendermaßen

    [list]
    [*]1
    [*]2
    [/list]
    

    Dann brauchst du auch nicht manuell Bindestriche zu setzen und es sieht besser aus.

    EDIT2 : Dass die Code Tags da nicht gehen scheint ein Problem mit dem Board zu sein.



  • Die Liste habe ich geändert, danke, das wusste ich vorher noch nicht!
    Die Zeilenumbrüche wollte ich eigentlich drinne lassen, damit es nicht so langgezogen aussieht. Falls es aber wirklich ein Problem sein sollte, nehme ich die natürlich auch noch raus.



  • Ist eher ein allgemeines Browserproblem. Allerdings ist dies auch nicht wirklich eine Lösung. Mach einfach mal dein Browserfenster ein paar Buchstaben schmaler als der Text. Die ganze Formatierung ist dann hin. IMHO ist es am besten die Formatierung den Browsers zu überlassen. Wer wirklich ein Problem mit langen Zeilen hat kann das Fenster ja schmaler machen.

    EDIT:
    Du hast vergessen die List Tags bei der Einteilung zu verbessern. Im Moment sieht es zwar auch so gut aus, allerdings wer weiß ob das noch so ist wenn Marc++us mal wieder an der Software rumschraubt.

    Ich würde auch noch UNREFERENCED_PARAMETER entweder rausnehmen oder einen Hinweis in den Text einbauen was dies sei. Es ist meiner Meinung nach kein besonders geläufiges Macro der WinAPI.



  • Das Makro habe ich erklärt, die Zeilenumbrüche rausgenommen. Hoffe das mundet 😉

    EDIT: und die Einteilung mit [*] versehen



  • return (iStatus == -1) ? false : true;
    // ...
    return (iStatus == -1 || iStatus == false) ? false : true;
    

    *hust*



  • Ist ein bisschen unsauber, aber ansonsten...soll ich das deiner Meinung nach ändern, oder war das bloß ein Wink mit dem Zaunpfahl.



  • Also, ich würde es ändern...
    Sieht verwirrend aus.



  • Geändert. 👍


Log in to reply