Iczelion - 31 - Listview Steuerelement

Tutorial 31: Listview Steuerelement



Wir werden in diesem Tutorial lernen, wie man ein Listview Steuerelement erzeugt und benutzt.

Laden Sie das Beispiel herunter.

Theorie:

Ein ListView Steuerelement ist ein Standard-Steuerelement wie TreeView, RichEdit, etc. Sie sind mit ihm vertraut, auch wenn Sie es vielleicht beim Namen kennen. Zum Beispiel ist die rechte Seite Hälfte des Windows Explorers ein ListView Steuerelement. Ein ListView Steuerelement ist gut geeignet um Items anzuzeigen. In dieser Hinsicht ist es wie eine ListBox, nur mit erweiterten Möglichkeiten.
Sie können ein ListView Steuerelement auf zwei Arten erzeugen. Die erste Methode ist auch die einfachste: erzeugen Sie es mit einem Ressource-Editor. Vergessen Sie nur nicht InitCommonControls in Ihrem Asm-Source Code aufzurufen. Die andere Methode ist CreateWindowEx in Ihrem Source Code aufzurufen. Sie müssen den korrekten Fenster-Klassen Namen für das Steuerelement angeben, d.h. SysListView32. Die Fenster-Klasse "WC_LISTVIEW" ist nicht korrekt.
Es gibt vier Methoden Daten in einem ListView Steuerelement anzusehen: Icon, kleines Icon, Listen und Report-Ansichten (Views). Sie können diese Ansichten beispielhaft betrachten, indem Sie im Beispiel View->Large Icons (Icon Ansicht), Small Icons (kleine Icons Ansicht), List (Listen Ansicht) und Details (Report Ansicht) wählen. Ansichten sind nur Daten Repräsentationen: Sie beeinflussen nur das Erscheinen der Daten. Sie können zum Beispiel eine Menge an Daten in Ihrem ListView Steuerelement haben, aber wenn Sie wollen, können Sie auch nur einige davon betrachten. Sie können die gewünschte Ansicht während der Erzeugung des ListView Steuerelementes angeben. Sie können später die Ansicht ändern, indem Sie SetWindowLong aufrufen und das GWL_STYLE Flag angeben.

Nun, da wir wissen, wie man ein ListView Steuerelement erzeugt, werden wir mit der Benutzung fortfahren. Ich werde mich auf die Report-Ansicht fokusieren, welche eine Menge Features demonstrieren kann. Die Schritte um ein ListView Steuerelement zu benutzen, sind folgende:

  1. Erzeugen Sie ein ListView Steuerelement mit CreateWindowEx und geben SysListView32 als den Klassen Namen an. Sie können zu diesem Zeitpunkt die initialisierende Ansicht angeben.
  2. (falls vorhanden) Erzeugen und initialisieren Sie Image Listen, die mit den ListView Items benutzt werden.
  3. Fügen Sie Spalten in das ListView Steuerelement ein. Dieser Schritt ist notwendig, wenn das ListView Steuerelement die Report Ansicht benutzt.
  4. Fügen Sie Items und Subitems in das ListView Steuerelement ein.

Spalten

In der Report Ansicht gibt es eine oder mehrere Spalten. Sie können sich die Anordnung der Daten in der Report Ansicht als eine Tabelle vorstellen: die Daten sind in Spalten und Zeilen organisiert. Sie müssen mindestens eine Spalte in Ihrem ListView Steuerelement haben (nur in der Report-Ansicht). In anderen Ansichten, müssen Sie keine Spalte einfügen, da nur eine und nur diese eine Spalten in diesen Ansichten vorhanden sein kann.
Sie können eine Spalte einfügen, indem Sie LVM_INSERTCOLUMN an das ListView Steuerelement senden.

LVM_INSERTCOLUMN
wParam = iCol
lParam = Zeiger auf eine LV_COLUMN Struktur

iCol ist die Spalten Nummer, bei 0 beginnend.
LV_COLUMN enthält Informationen über die einzufügende Spalte. Sie hat folgende Definition:

LV_COLUMN STRUCT imask dd ? fmt dd ? lx dd ? pszText dd ? cchTextMax dd ? iSubItem dd ? iImage dd ? iOrder dd ? LV_COLUMN ENDS


Feld Name Bedeutung
imask Eine Ansammlung von Flags, die regeln welche Elemente in der Struktur gültig sind. Der Grund für dieses Element ist, das nicht alle Elemente in dieser Struktur zur selben Zeit benutzt werden. Einige Elemente werde in bestimmten Situationen benutzt. Und diese Struktur wird sowohl für Ein-, als auch Ausgaben benutzt. Deshalb ist es wichtig, dass Sie die Elemente *markieren* die in diesem Aufruf benutzt werden, so das Windows weiß, welche Elemente gültig sind. Die verfügbaren Flags sind:

LVCF_FMT = Das fmt Element ist gültig.
LVCF_SUBITEM = Das iSubItem Element ist gültig.
LVCF_TEXT = Das pszText Element ist gültig.
LVCF_WIDTH = Das lx Element ist gültig.

Sie können die obigen Flags miteinander kombinieren. Wenn Sie zum Beispiel das Text Label der Spalte angeben wollen, müssen Sie den Zeiger auf den String im pszText Element angeben. Und Sie MÜSSEN Windows mitteilen, dass das pszText Element Daten enthält, indem Sie das LVCF_TEXT Flag in diesem Feld angeben, ansonsten ignoriert Windows den Wert in pszText.

fmt Spezifiziert die Ausrichtung der Items/Subitems in der Spalte. Verfügbare Werte sind:

LVCFMT_CENTER = Text ist zentriert.
LVCFMT_LEFT = Text ist links-ausgerichtet.
LVCFMT_RIGHT = Text ist rechts-ausgerichtet.

lx Die Breite der Spalte in Pixeln. Sie können die Breite der Spalte später mit LVM_SETCOLUMNWIDTH ändern.
pszText Enthält einen Zeiger auf den Namen der Spalte, wenn diese Struktur benutzt wird, um die Spalten-Eigenschaften zu setzen. Wenn diese Struktur benutzt wird, um die Eigenschaften einer Spalte zu ermitteln, enthält dieses Feld einen Zeiger auf einen Buffer, der groß genug ist, um den Namen der Spalte aufzunehmen, der zurückgeliefert wird. Für diesen Fall, müssen Sie die Größe des Buffers unten in cchTextMax angeben. Sie können cchTextMax ignorieren, wenn Sie den Namen der Spalte setzen wollen, da der Name ein ASCIIZ String sein muss, wo Windows die Länge bestimmen kann.
cchTextMax Die Größe des Buffers, der in pszText angegeben ist, in Bytes. Dieses Element wird nur benutzt wenn Sie diese Struktur benutzen, um Informationen über die Spalte zu erhalten. Wenn Sie diese Struktur benutzen, um die Eigenschaften der Spalte zu setzen, wird dieses Feld ignoriert.
iSubItem Spezifiziert den Index des Subitems, dass mit dieser Spalte verbunden ist. Dieser Wert wird als Marker benutzt, mit welchem SubItem dis Spalte verbunden ist. Wenn Sie wollen, können Sie hier eine völlig absurde Zahl angeben und ihr ListView Steuerelement wird immer noch wie geschmiert laufen. Die Nutzung dieses Feldes wird am besten demonstriert, wenn Sie die Spalten Nummer haben und Sie wissen müssen, welches SubItem mit der Spalte verbunden ist. Sie können das ListView Steuerelement fragen, indem Sie eine LVM_GETCOLUMN Nachrcith an es senden und LVCF_SUBITEM im imask Element angeben. Das ListView Steuerelement wird das iSubItem Element mit dem Wert füllen, den Sie in diesem Feld hier angeben, wenn die Spalte eingefügt wird. Damit diese Methode funktionieren kann, müssen Sie einen korrekten SubItem Index in diesem Feld speichern.
iImage und iOrder Wird mit Internet Explorer 3.0 und aufwärts benutzt. Ich habe keine Informationen darüber.
Nachdem das ListView Steuerelement erzeugt wurde, sollten Sie eine oder mehrere Spalten einfügen. Spalten sind nicht notwendig, wenn Sie nicht vorhaben, in die Report Ansicht zu wechseln. Um eine Spalte einzufügen, müssen Sie eine LV_COLUMN Struktur erzeugen, sie mit den nötigen Informationen füllen, die Spalten Nummer angeben und dann die Struktur mit der LVM_INSERTCOLUMN Nachricht an das ListView Steuerelement senden.

LOCAL lvc:LV_COLUMN mov lvc.imask,LVCF_TEXT+LVCF_WIDTH mov lvc.pszText,offset Heading1 mov lvc.lx,150 invoke SendMessage,hList, LVM_INSERTCOLUMN,0,addr lvc


Der obige Code Ausschnitt demonstriert den Prozess. Er spezifiziert den Spalten-Kopf-Text und die Breite und sendet dann die LVM_INSERTCOLUMN Nachicht an das ListView Steuerelement. So einfach ist das.

Items und Subitems

Items sind die Haupteinträge im ListView Steuerelement. In anderen Ansichten, als der Report Ansicht, werden Sie nur Items im ListView Steuerelement sehen. SubItems sind Details von Items. Ein Item kann ein oder mehrere SubItems haben. Wenn das Item zum Beispiel der Name einer Datei ist, dann können Sie die Dateiattribute, seine Größe, das Datum der Datei-Erzeugung als SubItem haben. In der Report Ansicht, enthält die linke Spalte Items und die übrigen Spalten SubItems. Sie können sich Items und SubItems als Datenbank-Satz vorstellen. Das Item ist der Haupt-Schlüssel, des Satzes und die SubItems sind die Felder.
Als Minimum müssen Sie mindestens einige Items in Ihrem ListView Steuerelement haben: SubItems sind nicht notwendig. Wenn Sie aber Informationen über das Item vermitteln wollen, können Sie SubItems hinzufügen, die der Benutzer in der Report Ansicht sehen kann.
Sie fügen ein Item in ein ListView Steuerelement ein, indem Sie die LVM_INSERTITEM Nachricht an es senden. Sie müssen auch die Adresse einer LV_ITEM Struktur in lParam an es übergeben. LV_ITEM hat folgende Definition:

LV_ITEM STRUCT imask dd ? iItem dd ? iSubItem dd ? state dd ? stateMask dd ? pszText dd ? cchTextMax dd ? iImage dd ? lParam dd ? iIndent dd ? LV_ITEM ENDS


Feld Name Bedeutung
imask Eine Ansammlung von Flags, die indizieren, welche Elemente in der Struktur für den Aufruf gültig sind. Generell ist diese Feld ähnlich zum imask Element vom obigen LV_COLUMN. Schauen Sie in Ihre Win32 API Referenz für mehr Details über verfügbare Flags.
iItem Der Index des Items auf die sich diese Struktur bezieht. Der Index ist null-basierend. Sie können sich das Feld so denken, als ob es die "Zeilen" Nummer einer Tabelle enthält.
iSubItem Der Index eines Subitems, das mit dem in iItem angegebenen Item verbunden ist. Sie können sich dieses Feld vorstellen, als ob es die "Spalten" einer Tabelle enthält. Wenn Sie zum Beispiel ein Item in ein neu erzeugtes ListView Steuerelement einfügen wollen, wäre der Wert in iItem 0 (da es das erste Item ist) und der Wert in iSubItem wäre auch 0 (wir wollen das Item in die erste Spalte einfügen). Wenn Sie ein SubItem angeben wollen, das mit diesem Item verbunden ist, wäre iItem der Index des Items, mit dem Sie es verbinden wollen (im obigen Beispiel ist es 0), wäre iSubItem 1 oder größer, abhängig von der Spalte, in der Sie das SubItem einfügen wollen. Wenn Ihr ListView Steuerelement zum Beispiel 4 Spalten hat, wird die erste die Items enthalten. Die übrigen 3 Spalten sind für SubItems. Wenn Sie ein SubItem in die vierte Spalte einfügen wollen, müssen Sie in iSubItem den Wert 3 angeben.
state Dieses Element enthält Flags, das den Status des Items reflektieren. Der Status eines Items kann sich ändern, auf Grund von Benutzer-Handlungen oder kann durch Ihr Programm modifiziert werden. Der Status umfasst, ob das Item den Fokus hat / gehilighted ist / selektiert für Ausschneide-Operationen / selektiert ist. Zusätzlich zu den Status-Flags, kann es auch einen Index des Overlay Image/State Image enthalten, dass vom Item benutzt wird.

stateMask Da das Status-Element sowohl Status-Flags, Overlay-Image Index als auch Status Image Index enthalten kann, müssen wir Windows mitteilene, welchen Wert wir setzen oder ermitteln wollen. Der Wert in deisem Feld ist für diesen Gebrauch.
pszText Die Adresse eines ASCIIZ Strings, der als Label des Items benutzt wird, für den Fall, dass wir das Item setzen/einfügen wollen. Für den Fall, dass wir die Item-Eigenschaften ermitteln wollen, benutzen wir diese Struktur und dieses Element muss die Adresse eines Buffers enthalten, der mit dem Item-Label gefüllt wird.
cchTextMax Dieses Feld wird nur benutzt, wenn Sie diese Struktur benutzen, um Informationen über ein Item zu ermitteln. In diesem Fall, enthält dieses Feld die Größe des Buffers auspszText in Bytes.
iImage Der Index in eine Image List, die die Icons für das ListView Steuerelement enthält. Dieser Index zeigt auf das Icon, das mit dem Item benutzt werden soll.
lParam Ein Benutzer-definierter Wert, der benutzt wird, wenn Sie Items in dem ListView Steuerelement sortieren. Kurz gesagt, wenn Sie dem ListView Steuerelement mitteilen, das es die ITems sortieren soll, wird das ListView Steuerelement die Items in Paaren vergleichen. Es wird den lParam Wert beide Items senden, so dass Sie entscheiden können, welches als erstes gelistet werden soll. Wenn Ihnen das noch unklar ist, machen Sie sich keinen Kopf. Sie werden später mehr über das Sortieren lernen.
Lassen Sie uns die Schritte nochmal zusammenfassen, die nötig sind, ein Item/SubItem in ein ListView Steuerelement einzufügen.

  1. Erzeugen Sie eine Variable vom Typ LV_ITEM Struktur
  2. Füllen Sie sie mit den nötigen Informationen
  3. Senden Sie eine LVM_INSERTITEM Nachricht an das ListView Steuerelement, wenn Sie ein Item einfügen wollen. Oder, wenn Sie ein SubItem *einfügen* wollen, senden Sie statt dessen LVM_SETITEM. Das ist ziemlich verwirrend, wenn Sie nicht die Beziehung zwischen Item und Subitems verstanden haben. Subitems werden als Eigenschaften eines Items betrachtet. Demnach können Sie Items einfügen, SubItems hingegen nicht und Sie können kein SubItem ohne zugehöriges Item haben. Deshalb müssen Sie eine LVM_SETITEM Nachricht senden, um ein SubItem hinzuzufügen, statt LVM_INSERTITEM.

ListView Nachrichten/Benachrichtigungen

Nun, da Sie wissen, wir man ein ListView Steuerelement erzeugt und bevölkert, ist der nächste Schritt die Kommunikation mit ihm. Ein ListView Steuerelement kommuniziert mit dem Parent-Fenster über Nachrichten und Benachrichtigungen. Das Parent-Fenster kann das ListView Steuerelement kontrollieren, indem es Nachrichten an es sendet. Das ListView Steuerelement benachrichtigt das Parent bei wichtigen/interessanten Ereignissen über WM_NOTIFY Nachrichten, so wie jedes andere Standard Steuerelement.

Items/Subitems sortieren

Sie können die Standard Sortier-Reihenfolge des ListView Steuerelementes angeben, indem Sie die Stile LVS_SORTASCENDING (aufsteigend) oder LVS_SORTDESCENDING (absteigend) in CreateWindowEx angeben. Diese beiden Stile sortieren die Items nur nach ihrem Label. Wenn Sie die Items in einer andere Reihenfolge sortieren wollen, müssen Sie die LVM_SORTITEMS Nachricht an das ListView Steuerelement senden.

LVM_SORTITEMS
wParam = lParamSort
lParam = pCompareFunction


lParamSort ist ein Benutzer-definierter Wert, der der Vergleich-Funktion übergeben wird. Sie können den Wert benutzen wie Sie wollen.
pCompareFunction ist die Adresse der benutzerdefinierten Funktion, die über den Ausgang des Vergleichs der Items in dem ListView Steuerelement entscheided.Die Funktion hat folgenden Prototyp:

CompareFunc proto lParam1:DWORD, lParam2:DWORD, lParamSort:DWORD

lParam1 und lParam2 sind die Werte im lParam Element von LV_ITEM das Sie angeben, wenn Sie die Items in das ListView Steuerelement einfügen.
lParamSort ist der Wert in wParam den Sie mit LVM_SORTITEMS senden.

Wenn das ListView Steuerelement die LVM_SORTITEMS Nachricht erhält, ruft es die in lParam der Nachricht angegebene Vergleichs-Funktion auf, wenn es uns nach dem Ergebnis eines Vergleiches zwischen zwei Items fragen muss. Kurz gesagt entscheided die Vergleichs-Funktion, welches Item vor dem anderen gesendet wird. Die Regel ist einfach: wenn die Funktion einen negativen Wert zurückliefert, bekommt das erste Item (repräsentiert von lParam1) den Vortritt. Wenn die Funktion einen positiven Wert zurückliefert, bekommt das zweite Item (repräsentiert von lParam2) den Vortritt. Wenn die Items gleich sind, muss 0 zurück geliefert werden.

Warum diese Methode arbeiten kann, ist der Wert in lParam der LV_ITEM Struktur. Wenn Sie die Items sortieren müssen (wenn z.B. der Benutzer den Spalten-Kopf anklickt), müssen Sie über ein Sortier-Schema nachdenken, dass gebrauch des Wertes aus dem lParam Element macht. In dem Beispiel, speicher ich den Index des Items in diesem Feld, so dass ich andere Informationen über das Item erhalten kann, indem ich eine LVM_GETITEM Nachricht sende. Beachten Sie, dass wenn die Items neu angeordnet werden, sich auch die Indize ändern. So dass, wenn die Sortierung in meinem Beispiel beendet ist, ich die Werte in lParam erneuern muss, um die neue Indize abzubilden. Wenn Sie wollen, dass die Items sortiert werden, wenn der Benutzer den Spalten-Kopf anklickt, müssen Sie eine LVN_COLUMNCLICK Benachrichtigungs Nachricht in Ihrer Fenster-Prozedur bearbeiten. LVN_COLUMNCLICK wird Ihrer Fenster-Prozedur über dieWM_NOTIFY Nachricht übergeben.

Beispiel:

Dieses Beispiel erzeugt ein ListView Steuerelement un füllt es mit den Namen und Größen der Dateien im aktuellen Verzeichnis. Die Stadard-Ansicht ist die Report Ansicht. In der Report Ansicht können Sie auf den Spalten-Kopf klicken und die Items werden in aufsteigender/absteigender Reihenfolge sortiert. Sie können die Ansicht via Menü auswählen. Wenn Sie ein Doppelklick auf ein Item tätitgen, wird eine Message Box mit dem Label des Items angezeigt.

.386 .model flat,stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc include \masm32\include\comctl32.inc includelib \masm32\lib\comctl32.lib includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib WinMain proto :DWORD,:DWORD,:DWORD,:DWORD IDM_MAINMENU equ 10000 IDM_ICON equ LVS_ICON IDM_SMALLICON equ LVS_SMALLICON IDM_LIST equ LVS_LIST IDM_REPORT equ LVS_REPORT RGB macro red,green,blue xor eax,eax mov ah,blue shl eax,8 mov ah,green mov al,red endm .data ClassName db "ListViewWinClass",0 AppName db "Testing a ListView Control",0 ListViewClassName db "SysListView32",0 Heading1 db "Filename",0 Heading2 db "Size",0 FileNamePattern db "*.*",0 FileNameSortOrder dd 0 SizeSortOrder dd 0 template db "%lu",0 .data? hInstance HINSTANCE ? hList dd ? hMenu dd ? .code start: invoke GetModuleHandle, NULL mov hInstance,eax invoke WinMain, hInstance,NULL, NULL, SW_SHOWDEFAULT invoke ExitProcess,eax invoke InitCommonControls WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD LOCAL wc:WNDCLASSEX LOCAL msg:MSG LOCAL hwnd:HWND mov wc.cbSize,SIZEOF WNDCLASSEX mov wc.style, NULL mov wc.lpfnWndProc, OFFSET WndProc mov wc.cbClsExtra,NULL mov wc.cbWndExtra,NULL push hInstance pop wc.hInstance mov wc.hbrBackground,COLOR_WINDOW+1 mov wc.lpszMenuName,IDM_MAINMENU mov wc.lpszClassName,OFFSET ClassName invoke LoadIcon,NULL,IDI_APPLICATION mov wc.hIcon,eax mov wc.hIconSm,eax invoke LoadCursor,NULL,IDC_ARROW mov wc.hCursor,eax invoke RegisterClassEx, addr wc invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst,NULL mov hwnd,eax invoke ShowWindow, hwnd,SW_SHOWNORMAL invoke UpdateWindow, hwnd .while TRUE invoke GetMessage, ADDR msg,NULL,0,0 .break .if (!eax) invoke TranslateMessage, ADDR msg invoke DispatchMessage, ADDR msg .endw mov eax,msg.wParam ret WinMain endp InsertColumn proc LOCAL lvc:LV_COLUMN mov lvc.imask,LVCF_TEXT+LVCF_WIDTH mov lvc.pszText,offset Heading1 mov lvc.lx,150 invoke SendMessage,hList, LVM_INSERTCOLUMN, 0, addr lvc or lvc.imask,LVCF_FMT mov lvc.fmt,LVCFMT_RIGHT mov lvc.pszText,offset Heading2 mov lvc.lx,100 invoke SendMessage,hList, LVM_INSERTCOLUMN, 1 ,addr lvc ret InsertColumn endp ShowFileInfo proc uses edi row:DWORD, lpFind:DWORD LOCAL lvi:LV_ITEM LOCAL buffer[20]:BYTE mov edi,lpFind assume edi:ptr WIN32_FIND_DATA mov lvi.imask,LVIF_TEXT+LVIF_PARAM push row pop lvi.iItem mov lvi.iSubItem,0 lea eax,[edi].cFileName mov lvi.pszText,eax push row pop lvi.lParam invoke SendMessage,hList, LVM_INSERTITEM,0, addr lvi mov lvi.imask,LVIF_TEXT inc lvi.iSubItem invoke wsprintf,addr buffer, addr template,[edi].nFileSizeLow lea eax,buffer mov lvi.pszText,eax invoke SendMessage,hList,LVM_SETITEM, 0,addr lvi assume edi:nothing ret ShowFileInfo endp FillFileInfo proc uses edi LOCAL finddata:WIN32_FIND_DATA LOCAL FHandle:DWORD invoke FindFirstFile,addr FileNamePattern,addr finddata .if eax!=INVALID_HANDLE_VALUE mov FHandle,eax xor edi,edi .while eax!=0 test finddata.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY .if ZERO? invoke ShowFileInfo,edi, addr finddata inc edi .endif invoke FindNextFile,FHandle,addr finddata .endw invoke FindClose,FHandle .endif ret FillFileInfo endp String2Dword proc uses ecx edi edx esi String:DWORD LOCAL Result:DWORD mov Result,0 mov edi,String invoke lstrlen,String .while eax!=0 xor edx,edx mov dl,byte ptr [edi] sub dl,"0" mov esi,eax dec esi push eax mov eax,edx push ebx mov ebx,10 .while esi > 0 mul ebx dec esi .endw pop ebx add Result,eax pop eax inc edi dec eax .endw mov eax,Result ret String2Dword endp CompareFunc proc uses edi lParam1:DWORD, lParam2:DWORD, SortType:DWORD LOCAL buffer[256]:BYTE LOCAL buffer1[256]:BYTE LOCAL lvi:LV_ITEM mov lvi.imask,LVIF_TEXT lea eax,buffer mov lvi.pszText,eax mov lvi.cchTextMax,256 .if SortType==1 mov lvi.iSubItem,1 invoke SendMessage,hList,LVM_GETITEMTEXT,lParam1,addr lvi invoke String2Dword,addr buffer mov edi,eax invoke SendMessage,hList,LVM_GETITEMTEXT,lParam2,addr lvi invoke String2Dword,addr buffer sub edi,eax mov eax,edi .elseif SortType==2 mov lvi.iSubItem,1 invoke SendMessage,hList,LVM_GETITEMTEXT,lParam1,addr lvi invoke String2Dword,addr buffer mov edi,eax invoke SendMessage,hList,LVM_GETITEMTEXT,lParam2,addr lvi invoke String2Dword,addr buffer sub eax,edi .elseif SortType==3 mov lvi.iSubItem,0 invoke SendMessage,hList,LVM_GETITEMTEXT,lParam1,addr lvi invoke lstrcpy,addr buffer1,addr buffer invoke SendMessage,hList,LVM_GETITEMTEXT,lParam2,addr lvi invoke lstrcmpi,addr buffer1,addr buffer .else mov lvi.iSubItem,0 invoke SendMessage,hList,LVM_GETITEMTEXT,lParam1,addr lvi invoke lstrcpy,addr buffer1,addr buffer invoke SendMessage,hList,LVM_GETITEMTEXT,lParam2,addr lvi invoke lstrcmpi,addr buffer,addr buffer1 .endif ret CompareFunc endp UpdatelParam proc uses edi LOCAL lvi:LV_ITEM invoke SendMessage,hList, LVM_GETITEMCOUNT,0,0 mov edi,eax mov lvi.imask,LVIF_PARAM mov lvi.iSubItem,0 mov lvi.iItem,0 .while edi>0 push lvi.iItem pop lvi.lParam invoke SendMessage,hList, LVM_SETITEM,0,addr lvi inc lvi.iItem dec edi .endw ret UpdatelParam endp ShowCurrentFocus proc LOCAL lvi:LV_ITEM LOCAL buffer[256]:BYTE invoke SendMessage,hList,LVM_GETNEXTITEM,-1, LVNI_FOCUSED mov lvi.iItem,eax mov lvi.iSubItem,0 mov lvi.imask,LVIF_TEXT lea eax,buffer mov lvi.pszText,eax mov lvi.cchTextMax,256 invoke SendMessage,hList,LVM_GETITEM,0,addr lvi invoke MessageBox,0, addr buffer,addr AppName,MB_OK ret ShowCurrentFocus endp WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM .if uMsg==WM_CREATE invoke CreateWindowEx, NULL, addr ListViewClassName, NULL, LVS_REPORT+WS_CHILD+WS_VISIBLE, 0,0,0,0,hWnd, NULL, hInstance, NULL mov hList, eax invoke InsertColumn invoke FillFileInfo RGB 255,255,255 invoke SendMessage,hList,LVM_SETTEXTCOLOR,0,eax RGB 0,0,0 invoke SendMessage,hList,LVM_SETBKCOLOR,0,eax RGB 0,0,0 invoke SendMessage,hList,LVM_SETTEXTBKCOLOR,0,eax invoke GetMenu,hWnd mov hMenu,eax invoke CheckMenuRadioItem,hMenu,IDM_ICON,IDM_LIST, IDM_REPORT,MF_CHECKED .elseif uMsg==WM_COMMAND .if lParam==0 invoke GetWindowLong,hList,GWL_STYLE and eax,not LVS_TYPEMASK mov edx,wParam and edx,0FFFFh push edx or eax,edx invoke SetWindowLong,hList,GWL_STYLE,eax pop edx invoke CheckMenuRadioItem,hMenu,IDM_ICON,IDM_LIST, edx,MF_CHECKED .endif .elseif uMsg==WM_NOTIFY push edi mov edi,lParam assume edi:ptr NMHDR mov eax,[edi].hwndFrom .if eax==hList .if [edi].code==LVN_COLUMNCLICK assume edi:ptr NM_LISTVIEW .if [edi].iSubItem==1 .if SizeSortOrder==0 || SizeSortOrder==2 invoke SendMessage,hList,LVM_SORTITEMS,1,addr CompareFunc invoke UpdatelParam mov SizeSortOrder,1 .else invoke SendMessage,hList,LVM_SORTITEMS,2,addr CompareFunc invoke UpdatelParam mov SizeSortOrder,2 .endif .else .if FileNameSortOrder==0 || FileNameSortOrder==4 invoke SendMessage,hList,LVM_SORTITEMS,3,addr CompareFunc invoke UpdatelParam mov FileNameSortOrder,3 .else invoke SendMessage,hList,LVM_SORTITEMS,4,addr CompareFunc invoke UpdatelParam mov FileNameSortOrder,4 .endif .endif assume edi:ptr NMHDR .elseif [edi].code==NM_DBLCLK invoke ShowCurrentFocus .endif .endif pop edi .elseif uMsg==WM_SIZE mov eax,lParam mov edx,eax and eax,0ffffh shr edx,16 invoke MoveWindow,hList, 0, 0, eax,edx,TRUE .elseif uMsg==WM_DESTROY invoke PostQuitMessage,NULL .else invoke DefWindowProc,hWnd,uMsg,wParam,lParam ret .endif xor eax,eax ret WndProc endp end start


Analyse:

Das erste was das Programm macht, wenn das Haupt-Fenster erzeugt ist, es wird ein ListView Steuerelement erzeugt.

.if uMsg==WM_CREATE invoke CreateWindowEx, NULL, addr ListViewClassName, NULL, LVS_REPORT+WS_CHILD+WS_VISIBLE, 0,0,0,0,hWnd, NULL, hInstance, NULL mov hList, eax


Wir rufen CreateWindowEx auf, übergeben ihr den Namen der Fenster-Klasse "SysListView32". Die Standard Ansicht ist die Report Ansicht, die mit dem LVS_REPORT Stil angegeben wird.

invoke InsertColumn


Nachdem das Listview Steuerelement erzeugt ist, fügen wir Spalten ein.

LOCAL lvc:LV_COLUMN mov lvc.imask,LVCF_TEXT+LVCF_WIDTH mov lvc.pszText,offset Heading1 mov lvc.lx,150 invoke SendMessage,hList, LVM_INSERTCOLUMN, 0, addr lvc


Wir geben das Label und die Breite der ersten Spalte an, um die Namen der Dateien in der LV_COLUMN Struktur zu speichern, weshalb wir imask mit den LVCF_TEXT und LVCF_WIDTH Flags setzen müssen. Wir füllen pszText mit der Adresse des Labels und lx mit der Breite der Spalte in Pixeln. Wenn alles getan ist, senden wir eine LVM_INSERTCOLUMN Nachricht an das ListView Steuerelement und übergeben ihr die Struktur.

or lvc.imask,LVCF_FMT mov lvc.fmt,LVCFMT_RIGHT


Wenn wir mit der Einfügung der erste Spalte fertig sind, fügen wir eine weitere Spalte ein, um die Größe der Dateien zu speichern. Da wir die Größe der Dateien rechtsausgerichtet benötigen, müssen wir ein Flag im fmt Element angeben, LVCFMT_RIGHT. Wir müssen auch das LVCF_FMT Flag in imask angeben, zusätzlich zu LVCF_TEXT und LVCF_WIDTH.

mov lvc.pszText,offset Heading2 mov lvc.lx,100 invoke SendMessage,hList, LVM_INSERTCOLUMN, 1 ,addr lvc


Der restliche Code ist einfach. Speichern Sie die Adresse des Labels in pszText und die Breite in lx. Dann senden Sie eine LVM_INSERTCOLUMN Nachricht an das ListView Steuerelement, die Spalten-Nummer und die Adresse der Struktur angebend.

Wenn die Spalten eingefügt sind, können wir die Items in das ListView Steuerelement einfügen.

invoke FillFileInfo


FillFileInfo hat folgenden Code.

FillFileInfo proc uses edi LOCAL finddata:WIN32_FIND_DATA LOCAL FHandle:DWORD invoke FindFirstFile,addr FileNamePattern,addr finddata


Wir rufen FindFirstFile auf, um Informationen über die erste, den Suchkriterien entsprechende Datei, zu erhalten. FindFirstFile hat folgenden Prototyp:

FindFirstFile proto pFileName:DWORD, pWin32_Find_Data:DWORD

pFileName ist die Adresse des zu suchenden Dateinamens. Dieser String kann Wildcards enthalten. In unserem Beispiel benutzen wir *.*, damit alle Dateien im aktuellen Verzeichnis gesucht werden.
pWin32_Find_Data ist die Adresse der WIN32_FIND_DATA Struktur, die mit den Information über die Datei gefüllt wird (wenn sie gefunden wird).

Diese Funktion liefert INVALID_HANDLE_VALUE in EAX zurück, wenn keine passende Datei gefunden wurde. Ansonsten wird ein Search- (Such-)Handle zurückgeliefert, das in drauffolgenden FindNextFile Aufrufen benutzt wird.

.if eax!=INVALID_HANDLE_VALUE mov FHandle,eax xor edi,edi


Wenn eine Datei gefunden wurde, speichern wir das Search-Handle in einer Variable und nullen dann EDI aus, was als Index der Items benutzt wird (Zeilen Nummer).

.while eax!=0 test finddata.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY .if ZERO?


In diesem Tutorial möchte ich mich nicht mit Verzeichnissen beschäftigen, weshalb ich diese herausgefiltert habe, indem dwFileAttributes auf Dateien überprüft wird, welche das FILE_ATTRIBUTE_DIRECTORY Flag gesetzt haben. Wenn sie gefunden sind, springe ich zum nächsten FindNextFile Aufruf.

invoke ShowFileInfo,edi, addr finddata inc edi .endif invoke FindNextFile,FHandle,addr finddata .endw


Wir fügen den Namen und die Größe der Datei in das ListView Steuerelement ein, indem wir die ShowFileInfo Funktion aufrufen. Dann erhöhen wir die aktuelle Zeilen Nummer in EDI. Als letztes fahren wir mit dem Aufruf von FindNextFile fort, um für nach der nächsten Datei im aktuellen Verzeichnis zu suchen, bis FindNextFile 0 zurück liefert (was bedeutet, das keine Dateien mehr gefunden wurden).

invoke FindClose,FHandle .endif ret FillFileInfo endp


Wenn alle Dateien im akutellen Verzeichnis aufgelistet sind, müssen wir das Search-Handle schließen.

Schauen wir uns nun die ShowFileInfo Funktion an. Diese Funktion erwartet zwei Parameter, den Index des Items (Zeilen Nummer) und die Adresse der WIN32_FIND_DATA Struktur.

ShowFileInfo proc uses edi row:DWORD, lpFind:DWORD LOCAL lvi:LV_ITEM LOCAL buffer[20]:BYTE mov edi,lpFind assume edi:ptr WIN32_FIND_DATA


Speichern Sie die Adresse der WIN32_FIND_DATA Struktur in EDI.

mov lvi.imask,LVIF_TEXT+LVIF_PARAM push row pop lvi.iItem mov lvi.iSubItem,0


Wir liefern das Label des Items und den Wert in lParam, weshalb wir die Flags LVIF_TEXT und LVIF_PARAM in der imask speichern. Als nächstes setzen wir das iItem auf die Zeilen Nummer, die an die Funktion überreicht wird und da das das Haupt-Item ist, müssen wir filliSubItem mit 0 (Spalte 0) füllen.

lea eax,[edi].cFileName mov lvi.pszText,eax push row pop lvi.lParam


Als nächstes speichern wir die Adresse des Labels, in diesem Fall den Namen der Datei in der WIN32_FIND_DATA Struktur, inpszText. Da wir Sortierung im ListView Steuerelement implementieren, müssen wir lParam mit einem Wert füllen. Ich habe die Zeilen Nummer gewählt, so dass ich die Infos über das Item über seinen Index ermitteln kann.

invoke SendMessage,hList, LVM_INSERTITEM,0, addr lvi


Wenn alle nötigen Felder in LV_ITEM gefüllt sind, senden wir eine LVM_INSERTITEM Nachricht an das ListView Steuerelement, um das Item einzufügen.

mov lvi.imask,LVIF_TEXT inc lvi.iSubItem invoke wsprintf,addr buffer, addr template,[edi].nFileSizeLow lea eax,buffer mov lvi.pszText,eax


Wir setzen das SubItem, das mit dem gerade eingefügten Item verbunden ist, in die zweite Spalte. Ein SubItem kann nur ein Label haben. Deshalb geben wir LVIF_TEXT in imask an. Dann geben wir die Spalte iSubItem an, wo sich das SubItem befinden soll. In diesem Fall, setzen wir es auf 1, indem wir iSubItem inkrementieren. Das Label, das benutzen werden, ist die Größe der Datei. Wir müssen sie also in erst in einen String konvertieren, indem wir wsprintf aufrufen. Dann speichern wir die Adresse des Strings in pszText.

invoke SendMessage,hList,LVM_SETITEM, 0,addr lvi assume edi:nothing ret ShowFileInfo endp


Wenn alle nötigen Felder in LV_ITEM gefüllt sind, senden wir eine LVM_SETITEM Nachricht an das ListView Steuerelement und übergeben die Adresse der LV_ITEM Struktur. Beachten Sie, dass wir LVM_SETITEM benutzen, nicht LVM_INSERTITEM, da ein SubItem als Eigenschaft eines Items betrachtet wird. Deswegen *setzen* wir die Eigenschaften des Items und fügen kein neues Item ein.

Wenn alle Items in das ListView Steuerelement eingefügt sind, setzen wir die Text und Hintergrund Farbe des ListView Steuerelementes.

RGB 255,255,255 invoke SendMessage,hList,LVM_SETTEXTCOLOR,0,eax RGB 0,0,0 invoke SendMessage,hList,LVM_SETBKCOLOR,0,eax RGB 0,0,0 invoke SendMessage,hList,LVM_SETTEXTBKCOLOR,0,eax


Ich benutze das RGB Makro, um die Rot, Grün, Blau Werte in EAX zu konvertieren und benutze es, um die Farbe, die wir benötigen, anzugeben. Wir sezten die Vordergrundfarbe und Hintergrundfarbe des Textes mit LVM_SETTEXTCOLOR und LVM_SETTEXTBKCOLOR Nachrichten. Wir setzen die Hintergrundfarbe des ListView Steuerelementes, indem wir eine LVM_SETBKCOLOR Nachricht an das ListView Steuerelement senden.

invoke GetMenu,hWnd mov hMenu,eax invoke CheckMenuRadioItem,hMenu,IDM_ICON,IDM_LIST, IDM_REPORT,MF_CHECKED


Wir werden den Benutzer die Ansicht, die er haben will, über das Menü auswählen lassen. Deshalb müssen wir das als erstes Menü-Handle ermitteln. Um dem Benutzer die aktuelle Ansicht zu verdeutlichen, packen wir ein Radio Button in unserem Menü. Das Menü-Item, dass die aktuelle Ansicht reflektiert, wird ein Radio Button vorgestellt. Deshalb rufen wir CheckMenuRadioItem auf. Diese Funktion packt den Radio Button vor das Menü-Item.

Beachten Sie, dass wir das ListView Steuerelement mit Höhe und Breite gleich 0 erzeugen. Die Größe wird später verändert, wenn das Parent-Fenster geändert wird. Auf diesem Weg können wir sicher sein, dass die Größe des ListView Steuerelements immer mit der Größe des Parent-Fensters übereinstimmt. In unserem Beispiel wollen wir das ListView Steuerelement immer über die gesamte Client Area des Parent-Fensters haben.

.elseif uMsg==WM_SIZE mov eax,lParam mov edx,eax and eax,0ffffh shr edx,16 invoke MoveWindow,hList, 0, 0, eax,edx,TRUE


Wenn das Parent-Fenster die WM_SIZE Nachricht erhält, enthält das untere Word von lParam die neue Breite der Client Area und das obere Word die neue Höhe. Dann rufen wir MoveWindow um das ListView Steuerelement in seiner Größe zu erneuern, damit die gesamte Client Area des Parent-Fensters abgedeckt ist.

Wenn der Benutzer eine Ansicht im Menü auswählt, müssen wir die Ansicht im ListView Steuerelement entsprechend ändern. Wir erreichen das, indem wir einen neuen Stil im ListView Steuerelement mit SetWindowLong setzen.

.elseif uMsg==WM_COMMAND .if lParam==0 invoke GetWindowLong,hList,GWL_STYLE and eax,not LVS_TYPEMASK


Das erste, was wir machen, ist das Ermitteln der aktuellen Stile des ListView Steuerelementes. Dann löschen wir den alten Ansichts-Stil aus den zurückgelieferten Stil Flags. LVS_TYPEMASK ist eine Konstante, die mit dem Wert alle 4 Ansichts Stil Konstanten kombiniert ist (LVS_ICON+LVS_SMALLICON+LVS_LIST+LVS_REPORT). Deshalb führen wir eine and Operation auf das aktuelle Stile Flags mit dem Wert "not LVS_TYPEMASK", aus, damit der aktuelle Ansichts Stil gelöscht wird.

Beim designen des Menüs habe ich ein wenig geschummelt. Ich benutze die Ansicht-Stil-Konstanten als die Menü-IDs.

IDM_ICON equ LVS_ICON IDM_SMALLICON equ LVS_SMALLICON IDM_LIST equ LVS_LIST IDM_REPORT equ LVS_REPORT


Deshalb ist, wenn das Parent-Fenster eine WM_COMMAND Nachricht erhält, der gewünschte Ansichts-Stil im unteren Word von wParam, als die Menü ID.

mov edx,wParam and edx,0FFFFh


Wir haben den gewünschten Ansichts Stil im unteren Word von wParam. Alles was wir machen müssen, ist das obere Word auszunullen.

push edx or eax,edx


Und den gewünschten Stil zu den existierenden Stilen (abzüglich des aktuellen Ansichts Stils) hinzu addieren.

invoke SetWindowLong,hList,GWL_STYLE,eax


Und die neuen Stile mit SetWindowLong setzen.

pop edx invoke CheckMenuRadioItem,hMenu,IDM_ICON,IDM_LIST, edx,MF_CHECKED .endif


Wir müssen auch noch den Radio Button vor unser selektiertes Menü-Item packen. Deshalb rufen wir CheckMenuRadioItem auf und übergeben ihr den aktuellen Ansichts Stil (doppelte der Menü ID).

Wenn der Benutzer während der Report Ansicht auf den Spalte-Kopf klickt, wollen wir die Items im ListView Steuerelement sortieren. Wir müssen auf die WM_NOTIFY Nachricht antworten.

.elseif uMsg==WM_NOTIFY push edi mov edi,lParam assume edi:ptr NMHDR mov eax,[edi].hwndFrom .if eax==hList


Wenn wir die WM_NOTIFY Nachricht erhalten, enthält lParam den Zeiger auf eine NMHDR Struktur. Wir können überprüfen, ob diese Nachricht vom ListView Steuerelement ist, indem wir das hwndFrom Element von NMHDR mit dem Handle des ListView Steuerelementes vergleichen. Wenn Sie übereinstimmen, können wir davon ausgehen, dass die Benachrichtigung vom ListView Steuerelement kam.

.if [edi].code==LVN_COLUMNCLICK assume edi:ptr NM_LISTVIEW


Wenn die Benachrichtigung vom ListView Steuerelement kan, überprüfen wir, ob der Code gleich LVN_COLUMNCLICK ist. Wenn ja, bedeutet das, dass der Benutzer auf den Spalten-Kopf geklickt hat. In diesem Fall, dass der Code gleich LVN_COLUMNCLICK ist, nehmen wir an, dass lParam den Zeiger auf eine NM_LISTVIEW Struktur enthält, welche eine Übermenge der NMHDR Struktur ist. Dann müssen wir wissen, auf welchen Spalten-Kopf der Benutzer geklickt hat. Eine Untersuchung des iSubItem Elementes liefert diese Information. Der Wert in iSubItem kann als Spalten Nummer behandelt werden, bei 0 beginnend.

.if [edi].iSubItem==1 .if SizeSortOrder==0 || SizeSortOrder==2


Wenn iSubItem 1 ist, bedeutet das, dass der Benutzer auf die zweite Spalte, Größe, geklickt hat. Wir benutzen Status-Variablen, um den aktuellen Status der Sortierreihenfolge zu behalten. 0 bedeutet "noch keine Sortierung", 1 bedeutet "aufsteigende Sortierung", 2 bedeutet "absteigende Sortierung". Wenn die Items/SubItems in der Spalte noch nicht sortiert wurden oder absteigend sortiert sind, setzen wir die Sortier-Reihenfolge auf aufsteigend.

invoke SendMessage,hList,LVM_SORTITEMS,1,addr CompareFunc


Wir senden eine LVM_SORTITEMS Nachricht an das ListView Steuerelement und übergeben in wParam 1 und die Adresse unserer Vergleichs-Funktion in lParam. Beachten Sie, dass der Wert in wParam Benutzer-definiert ist, Sie können ihn behandeln wie Sie wollen. Ich benutze die Sortier-Methode in diesem Beispiel. Wir werfen erst ein Blick auf die Vergleichs-Funktion.

CompareFunc proc uses edi lParam1:DWORD, lParam2:DWORD, SortType:DWORD LOCAL buffer[256]:BYTE LOCAL buffer1[256]:BYTE LOCAL lvi:LV_ITEM mov lvi.imask,LVIF_TEXT lea eax,buffer mov lvi.pszText,eax mov lvi.cchTextMax,256


In der Vergleichs-Funktion überreicht das ListView Steuerelement lParams (in LV_ITEM) der zwei Items an uns, welche vergleicht werden sollen, in lParam1 und lParam2. Sie werden sich erinnern, dass wir den Index des Item in lParam gespeichert haben. Deshalb können wir Informationen über die Items erhalten, indem wir das ListView Steuerelement abfragen, indem wir die Indize benutzen. Die Info, die wir benötigen, ist das Label des Items/SubItems, welche sortiert werden. Deshalb bereiten wir eine LV_ITEM Struktur für das Vorhaben vor und geben LVIF_TEXT in imask an und die Adresse des Buffers in pszText und die Größe des Buffers in cchTextMax.

.if SortType==1 mov lvi.iSubItem,1 invoke SendMessage,hList,LVM_GETITEMTEXT,lParam1,addr lvi


Wenn der Wert in SortType 1 oder 2 ist, wissen wir, dass die Größe-Spalte angeklickt wurde. 1 bedeutet, dass die Items bezüglich ihrer Größe aufsteigend sortiert wurden. 2 bedeutet das Gegenteil. Deshalb geben wir in iSubItem als 1 an ( um die Größe-Spalte zu spezifizeren) und senden eine LVM_GETITEMTEXT Nachricht an das ListView Steuerelement, um das Label (Größe-String) des SubItems zu erhalten.

invoke String2Dword,addr buffer mov edi,eax


Konvertiert den Größe-String in ein DWord Wert mit String2Dword, was eine Funktion ist, die ich geschrieben habe. Sie liefert den DWord Wert in EAX zurück. Wir speichern ihn in EDI für späteren Vergleich.

invoke SendMessage,hList,LVM_GETITEMTEXT,lParam2,addr lvi invoke String2Dword,addr buffer sub edi,eax mov eax,edi


Mache das selbe mit dem Wert in lParam2. Wenn wir die Größe der beiden Dateien haben, können wir sie vergleichen.
Die Regel der Vergleichs-Funktion ist folgende:

  • Wenn das erste Item vor dem anderen kommen soll, müssen Sie einen negativen Wert in EAX zurückgeben.
  • Wenn das zweite Item vor dem ersten kommen soll, müssen Sie einen positiven Wert in EAX zurückgeben.
  • Wenn beide Items gleich sind, müssen Sie 0 in EAX zurückgeben.
In diesem Fall, möchten wir die Items bezüglich ihrer Größe in aufsteigender Reihenfolge sortieren. Deshalb können wir einfach die Größe des ersten Items vom zweiten subtrahieren und das Ergebnis in EAX zurückgeben.

.elseif SortType==3 mov lvi.iSubItem,0 invoke SendMessage,hList,LVM_GETITEMTEXT,lParam1,addr lvi invoke lstrcpy,addr buffer1,addr buffer invoke SendMessage,hList,LVM_GETITEMTEXT,lParam2,addr lvi invoke lstrcmpi,addr buffer1,addr buffer


Für den Fall, dass der Benutzer auf die Dateinamen-Spalte klickt, müssen wir die Namen der Dateien vergleichen. Wir ermitteln die Dateinamen und vergleichen sie dann mit der lstrcmpi Funktion. Wir können den Rückgabewert von lstrcmpi ohne Änderung einfach zurückgeben, da sie die selbe Regeln für den Vergleich benutzt, d.h. negative Wert in EAX, wenn der erste String kleiner als der zweite String ist.

Wenn die Items sortiert sind, müssen wir die lParam Werte aller Items aktuallisieren um die neuen Indize zu reflektieren, indem wir die UpdatelParam Funktion aufrufen.

invoke UpdatelParam mov SizeSortOrder,1


Diese Funktion zählt einfach alle Items aus dem ListView Steuerelement auf und aktuallisiert die Wert in lParam mit den neuen Indizes. Wir müssen das tun, da ansonsten der nächste Sortiervorgang nicht mehr wie erwartet funktioniert, auf Grund unserer Annahme, dass der Wert in lParam der Index des Items ist.

.elseif [edi].code==NM_DBLCLK invoke ShowCurrentFocus .endif


Wenn der Benutzer einen Doppelklick auf ein Item tätigt, wollen wir eine Message Box mit dem Label des Items anzeigen. Wir müssen überprüfen, ob der Code in NMHDR gleich NM_DBLCLK ist. Wenn ja, können wir mit der Ermittlung des Label fortfahren und es in einer Message Box anzeigen.

ShowCurrentFocus proc LOCAL lvi:LV_ITEM LOCAL buffer[256]:BYTE invoke SendMessage,hList,LVM_GETNEXTITEM,-1, LVNI_FOCUSED


Wie wissen wir, welches Item mit einem Doppelklick angeklickt wurde? Wenn ein Item einfach oder doppelt geklickt wird, wird sein Status auf "focused" (fokussiert) gesetzt. Selbst wenn mehrere Items selektiert sind, hat nur eins davon den Fokus. Unsere Aufgabe ist es dann, dieses zu finden, das den Fokus hat. Wir machen das, indem wir eine LVM_GETNEXTITEM Nachricht an das ListView Steuerelement senden und den gewünschten Status in lParam angeben. -1 in wParam bedeutet, dass nach allen Items gesucht wird. Der Index des Items wird in EAX zurück geliefert.

mov lvi.iItem,eax mov lvi.iSubItem,0 mov lvi.imask,LVIF_TEXT lea eax,buffer mov lvi.pszText,eax mov lvi.cchTextMax,256 invoke SendMessage,hList,LVM_GETITEM,0,addr lvi


Wir fahren dann fort, um das Label zu ermitteln, indem wir eine LVM_GETITEM Nachricht an das ListView Steuerelement senden.

invoke MessageBox,0, addr buffer,addr AppName,MB_OK


Zu guter letzt zeigen wir das Label in einer Message Box an.

Wenn Sie wissen wollen, wie man Icons im ListView Steuerelement benutzt, können Sie in meinem TreeView Tutorial nachlesen. Die Schritte sind genau die selben.


Deutsche Übersetzung: Joachim Rohde
Die original Win32Asm-Tutorials stammen von Iczelion's Win32 Assembly HomePage