📄 lion-tutorial31.htm
字号:
</tr>
<tr>
<td>lParam</td>
<td>A user-defined value that will be used when you sort items in the listview
control. In short, when you tell the listview control to sort the items,
the listview control will compare the items in pairs. It will send the <b>lParam</b>
values of both items to you so you can decide which of the two should be
listed first. If you're still hazy about this, don't worry. You'll learn
more about sorting later.</td>
</tr>
</table>
<p>Let's summarize the steps in inserting an item/subitem into a listview control.</p>
<ol>
<li>Create a variable of type <b>LV_ITEM</b> structure</li>
<li>Fill it with necessary information</li>
<li>Send <b>LVM_INSERTITEM</b> message to the listview control if you want to
insert an item. Or if you want to *insert* a subitem, send <b>LVM_SETITEM</b>
instead. This is rather confusing if you don't understand the relationship
between an item and its subitems. <b>Subitems are considered as properties
of an item</b>. Thus you can insert items but not subitems and you can't have
a subitem without an associated item. That's why you need to send <b>LVM_SETITEM</b>
message to add a subitem instead of <b>LVM_INSERTITEM</b>. </li>
</ol>
<h3>ListView Messages/Notifications</h3>
<p>Now that you know how to create and populate a listview control, the next step
is to communicate with it. A listview control communicates with the parent window
via messages and notifications. The parent window can control the listview control
by sending messages to it. The listview control notifies the parent of important/interesting
events via <b>WM_NOTIFY</b> message, just like other common controls.</p>
<h3>Sorting items/subitems</h3>
<p>You can specify the default sorting order of a listview control by specifying
<b>LVS_SORTASCENDING</b> or <b>LVS_SORTDESCENDING</b> styles in <b>CreateWindowEx</b>.
These two styles order the items using their labels only. If you want to sort
the items in other ways, you need to send <b>LVM_SORTITEMS</b> message to the
listview control.</p>
<blockquote>
<p><b>LVM_SORTITEMS<br>
wParam = lParamSort<br>
lParam = pCompareFunction</b></p>
</blockquote>
<p><b>lParamSort </b>is a user-defined value that will be passed to the compare
function. You can use this value in any way you want.<br>
<b>pCompareFunction</b> is the address of the user-defined function that will
decide the outcome of the comparison of items in the listview control. The function
has the following prototype:</p>
<p><b>CompareFunc proto lParam1:DWORD, lParam2:DWORD, lParamSort:DWORD</b></p>
<p><b>lParam1</b> and <b>lParam2</b> are the values in <b>lParam</b> member of
<b>LV_ITEM</b> that you specify when you insert the items into the listview
control.<br>
<b>lParamSort</b> is the value in wParam you sent with <b>LVM_SORTITEMS</b></p>
<p>When the listview control receives<b> LVM_SORTITEMS</b> message, it calls the
compare function specified in<b> lParam</b> of the message when it needs to
ask us for the result of comparison between two items. In short, the comparison
function will decide which of the two items sent to it will precede the other.
The rule is simple: if the function returns a negative value, the first item
(represented by<b> lParam1</b>) should precede the other. If the function returns
a positive value, the second item (represented by <b>lParam2</b>) should precede
the first one. If both items are equal, it must return zero. </p>
<p>What makes this method work is the value in <b>lParam</b> of <b>LV_ITEM</b>
structure. If you need to sort the items (such as when the user clicks on a
column header), you need to think of a sorting scheme that makes use of the
values in lParam member. In the example, I put the index of the item in this
field so I can obtain other information about the item by sending <b>LVM_GETITEM</b>
message. Note that when the items are rearranged, their indexes also change.
So when the sorting is done in my example, I need to update the values in lParam
to reflect the new indexes. If you want to sort the items when the user clicks
on a column header, you need to process <b>LVN_COLUMNCLICK</b> notification
message in your window procedure. <b>LVN_COLUMNCLICK</b> is passed to your window
proc via <b>WM_NOTIFY</b> message.</p>
<h3>Example:</h3>
<p>This example creates a listview control and fills it with the names and sizes
of the files in the current folder. The default view is the report one. In the
report view, you can click on the column heads and the items will be sorted
in ascending/descending order. You can select the view you want via the menu.
When you double-click on an item, a message box showing the label of the item
is displayed.</p>
<p>.386 <br>
.model flat,stdcall <br>
option casemap:none <br>
include \masm32\include\windows.inc <br>
include \masm32\include\user32.inc <br>
include \masm32\include\kernel32.inc <br>
include \masm32\include\comctl32.inc <br>
includelib \masm32\lib\comctl32.lib <br>
includelib \masm32\lib\user32.lib <br>
includelib \masm32\lib\kernel32.lib <br>
<br>
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD <br>
<br>
IDM_MAINMENU equ 10000 <br>
IDM_ICON equ LVS_ICON <br>
IDM_SMALLICON equ LVS_SMALLICON <br>
IDM_LIST equ LVS_LIST <br>
IDM_REPORT equ LVS_REPORT <br>
<br>
RGB macro red,green,blue <br>
xor eax,eax <br>
mov ah,blue <br>
shl eax,8 <br>
mov ah,green <br>
mov al,red <br>
endm <br>
<br>
.data <br>
ClassName db "ListViewWinClass",0 <br>
AppName db "Testing a ListView Control",0 <br>
ListViewClassName db "SysListView32",0 <br>
Heading1 db "Filename",0 <br>
Heading2 db "Size",0 <br>
FileNamePattern db "*.*",0 <br>
FileNameSortOrder dd 0 <br>
SizeSortOrder dd 0 <br>
template db "%lu",0<br>
<br>
.data? <br>
hInstance HINSTANCE ? <br>
hList dd ? <br>
hMenu dd ? <br>
<br>
.code <br>
start: <br>
invoke GetModuleHandle, NULL <br>
mov hInstance,eax <br>
invoke WinMain, hInstance,NULL, NULL, SW_SHOWDEFAULT <br>
invoke ExitProcess,eax <br>
invoke InitCommonControls <br>
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
<br>
LOCAL wc:WNDCLASSEX <br>
LOCAL msg:MSG <br>
LOCAL hwnd:HWND<br>
<br>
mov wc.cbSize,SIZEOF WNDCLASSEX <br>
mov wc.style, NULL <br>
mov wc.lpfnWndProc, OFFSET WndProc <br>
mov wc.cbClsExtra,NULL <br>
mov wc.cbWndExtra,NULL <br>
push hInstance <br>
pop wc.hInstance <br>
mov wc.hbrBackground,COLOR_WINDOW+1 <br>
mov wc.lpszMenuName,IDM_MAINMENU <br>
mov wc.lpszClassName,OFFSET ClassName <br>
invoke LoadIcon,NULL,IDI_APPLICATION <br>
mov wc.hIcon,eax <br>
mov wc.hIconSm,eax <br>
invoke LoadCursor,NULL,IDC_ARROW <br>
mov wc.hCursor,eax <br>
invoke RegisterClassEx, addr wc <br>
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst,NULL <br>
mov hwnd,eax <br>
invoke ShowWindow, hwnd,SW_SHOWNORMAL <br>
invoke UpdateWindow, hwnd <br>
.while TRUE <br>
invoke GetMessage, ADDR msg,NULL,0,0 <br>
.break .if (!eax) <br>
invoke TranslateMessage, ADDR msg <br>
invoke DispatchMessage, ADDR msg <br>
.endw <br>
mov eax,msg.wParam <br>
ret <br>
WinMain endp <br>
<br>
InsertColumn proc <br>
LOCAL lvc:LV_COLUMN <br>
<br>
mov lvc.imask,LVCF_TEXT+LVCF_WIDTH <br>
mov lvc.pszText,offset Heading1 <br>
mov lvc.lx,150 <br>
invoke SendMessage,hList, LVM_INSERTCOLUMN, 0, addr lvc<br>
or lvc.imask,LVCF_FMT<br>
mov lvc.fmt,LVCFMT_RIGHT <br>
mov lvc.pszText,offset Heading2 <br>
mov lvc.lx,100<br>
invoke SendMessage,hList, LVM_INSERTCOLUMN, 1 ,addr lvc <br>
ret <br>
InsertColumn endp <br>
<br>
ShowFileInfo proc uses edi row:DWORD, lpFind:DWORD <br>
LOCAL lvi:LV_ITEM <br>
LOCAL buffer[20]:BYTE <br>
mov edi,lpFind <br>
assume edi:ptr WIN32_FIND_DATA <br>
mov lvi.imask,LVIF_TEXT+LVIF_PARAM <br>
push row <br>
pop lvi.iItem <br>
mov lvi.iSubItem,0 <br>
lea eax,[edi].cFileName <br>
mov lvi.pszText,eax <br>
push row <br>
pop lvi.lParam <br>
invoke SendMessage,hList, LVM_INSERTITEM,0, addr lvi <br>
mov lvi.imask,LVIF_TEXT <br>
inc lvi.iSubItem <br>
invoke wsprintf,addr buffer, addr template,[edi].nFileSizeLow <br>
lea eax,buffer <br>
mov lvi.pszText,eax <br>
invoke SendMessage,hList,LVM_SETITEM, 0,addr lvi <br>
assume edi:nothing <br>
ret <br>
ShowFileInfo endp <br>
<br>
FillFileInfo proc uses edi <br>
LOCAL finddata:WIN32_FIND_DATA <br>
LOCAL FHandle:DWORD <br>
<br>
invoke FindFirstFile,addr FileNamePattern,addr finddata <br>
.if eax!=INVALID_HANDLE_VALUE <br>
mov FHandle,eax <br>
xor edi,edi <br>
.while eax!=0 <br>
test finddata.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY
<br>
.if ZERO?<br>
invoke ShowFileInfo,edi, addr
finddata <br>
inc edi <br>
.endif <br>
invoke FindNextFile,FHandle,addr finddata <br>
.endw <br>
invoke FindClose,FHandle <br>
.endif <br>
ret <br>
FillFileInfo endp <br>
<br>
String2Dword proc uses ecx edi edx esi String:DWORD <br>
LOCAL Result:DWORD <br>
<br>
mov Result,0 <br>
mov edi,String <br>
invoke lstrlen,String <br>
.while eax!=0 <br>
xor edx,edx <br>
mov dl,byte ptr [edi] <br>
sub dl,"0" <br>
mov esi,eax <br>
dec esi <br>
push eax <br>
mov eax,edx <br>
push ebx <br>
mov ebx,10 <br>
.while esi > 0 <br>
mul ebx <br>
dec esi <br>
.endw <br>
pop ebx <br>
add Result,eax <br>
pop eax <br>
inc edi <br>
dec eax <br>
.endw <br>
mov eax,Result <br>
ret <br>
String2Dword endp <br>
<br>
CompareFunc proc uses edi lParam1:DWORD, lParam2:DWORD, SortType:DWORD <br>
LOCAL buffer[256]:BYTE <br>
LOCAL buffer1[256]:BYTE <br>
LOCAL lvi:LV_ITEM <br>
<br>
mov lvi.imask,LVIF_TEXT <br>
lea eax,buffer <br>
mov lvi.pszText,eax <br>
mov lvi.cchTextMax,256 <br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -