日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux sort -w32,WIN32汇编: 31.列表视图控件

發布時間:2025/3/20 linux 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux sort -w32,WIN32汇编: 31.列表视图控件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第三十一課 列表視圖控件

本課中我們將學習如何創建和使用列表視圖控件。

理論:

列表視圖控件和樹型視圖、豐富文本編輯控件一樣是通用控件的一種??赡苣家呀浿懒肆斜硪晥D控件,只不過是不知道它的確切名字而已。列表視圖控件可以用來很好地顯示項目。在這方面它和列表框相同,只不過它的性能更強。

有兩種方法創建一個列表視圖控件。第一種也是最簡單的方法是:用資源編輯器來創建它。用該種方法只是不要忘記在您的代碼(的任何位置處)加入對InitCommonControls函數的調用(記得嗎,調用該函數只是為了隱式地加載包含通用控件的DLL)。另一種方法是調用CreateWindowEx函數,這里您必須指定合適的類名,譬如:SysListView32,WC_LISTVIEW不是正確的類名

在列表視圖種有四種方法來顯示數據:大圖標,小圖標,列表和報告方式。這些方法和在資源管理器種選擇View->Large Icons,Small Icons , List 和 Details 相對應。各種不同的顯示方式只是顯示了不同的外觀而已。譬如,您可能有許多的數據,只是并不想全部顯示。報告方式提供的消息最完全,其它的方式則要少得多。在剛創建一個列表視圖時您可以選擇一種初始顯示方法,隨后您可以調用SetWinodwLong函數并設置GWL_STYLE標志位來改變顯示方式

既然我們已經知道了如何創建列表控件,接下來我們學習如何使用它們。我們將主要集中在報告方式的顯示上,因為該種方式演示了最多的列表控制的特性。使用列表控制的步驟如下:

調用CreateWindowEx函數來創建一個列表控件,指定它的類名為SysListView32。您還可以在此處指定控件初次顯示時的方式。

創建和初始化用在列表控件中顯示項目的圖象列表(如果存在)。

向列表控件中插入列,如果顯示的方式是報告方式這一步是必須的。

向控件中插入項目和自項目。

列:

在報告方式中,有不止一個列。您可以把放入到列表控件中的數據看作是一張表單:這時數據是按行列排列的。在控件中至少有一列。在其它的顯示方式中則無所謂,因為這些顯示方式有僅有一列。

加入列要通過向列表控件發送LVM_INSERTCOLUMN消息來實現。

LVM_INSERTCOLUMN

wParam = iCol

lParam =指向LV_COLUMN型結構體變量的指針

iCol 列數,從0開始編號。

LV_COLUMN 包含了將插入的列的信息。它的定義如下:

LV_COLUMN STRUCT

imask dd ?

fmt dd ?

lx dd ?

pszText dd ?

cchTextMax dd ?

iSubItem dd ?

iImage dd ?

iOrder dd ?

LV_COLUMN ENDS

Field name

Meanings

imask

一組標志位,它指示了該結構體中的那些成員變量是有效的。該結構體中的成員變量并不是同時有效的。在某些時候,可能只有某些成員變量是有效的。結構體可以用來輸入和輸出。這樣讓WINDOWS知道那些成員變量是有效的是非常重要的。可能的標志有:

LVCF_FMT = fmt有效

LVCF_SUBITEM = iSubItem有效

LVCF_TEXT = pszText有效.

LVCF_WIDTH = lx有效

您可以一次使用幾個標志。譬如,如果您向指定列的文本標簽(列名),您必須在pszText成員變量中提供列名,然后指定標志LVCF_TEXT告訴WINDOWS成員變量pszText中的值是有效的,否則WINDOWS將忽略掉pszText中的值。

fmt

指定了項目/子項目的對齊方式??赡艿闹涤?#xff1a;

LVCFMT_CENTER = 文本居中

LVCFMT_LEFT = 文本左對齊

LVCFMT_RIGHT = 文本右對齊

lx

lx 是列的寬度(以像素點為單位)。以后您可以發送消息LVM_SETCOLUMNWIDTH來改變列的寬度。

pszText

如果用來設定列的屬性時,該成員變量為指向列名的指針。如果是查詢列名,該成員變量指向一個足夠大的緩沖區,用來接收返回的列名,這是您必須在成員cchTextMax中指定緩沖區的大小。如果是設定列名時,可以忽略該變量,因為該指針指向的是一個ASCII碼的字符串,而WINDOWS可以解析出ASCII串的長度。

cchTextMax

cchTextMax 以字節計的上面一個成員變量指向的緩沖區的小。該成員變量只在您查詢列的屬性時使用。如果是設定列的屬性,那該變量將被忽略。

iSubItem

指定和該列相連的子項目的索引號。該成員變量的值用來標識和列相連系的子項目。該列的使用最好地說明了如何把列號和子項目相連。要查詢列的屬性時可以發送LVM_GETCOLUMN消息,并在成員變量imask中指定LVCF_SUBITEM標志,列表控件將在iSubItem中返回插入時設定的iSubItem值。為了使用該辦法,您需要在該成員變量中放入正確的值。

iImage and iOrder

為了和IE3.0以上版本兼容。目前我沒有這方面的資料。

在列表視圖控件創建后,您必須至少向其中插入一列。當然如果不打算使用報告方式顯示,那倒是沒有必要插入列。為了插入列,您需要定義一個LV_COLUMN型的結構體變量,給其成員變量賦上正確的值,指定列號,然后向列表視圖控件發送LVM_INSERTCOLUMN消息并把該結構體變量的值傳過去。

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

上面的代碼段顯示了該過程。當發送LVM_INSERTCOLUMN消息時,他指定了列的標題條文本和它的寬度。

項目和子項目

項目是列表視圖中主要的內容。除報告方式顯示的外,在列表視圖您只能看到項目。子項目是項目的詳細信息。一個項目可能有不止一個相關的子項目。舉個例子,譬如項目是文件名,那其相關的子項目可能有文件屬性、大小、創建日期等。在報告方式的視圖中,最左邊一列是項目,其它列是子項目。從數據庫記錄的角度看,項目類似主鍵,子項目類似記錄。

至少您的列表視圖需要一些項目:子項目是可選的。如果您想要給用戶提供更多的信息,可以把子項目和項目相連,然后放到列表視圖中以報告的方式顯示。

您可以通過向列表視圖發送LVM_INSERTITEM消息來向其中添加項目,這時還需要把一個指向LV_ITEM型的結構體的變量的指針放到lParam一同傳給列表視圖。LV_ITEM的定義如下:

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

Field name

Meanings

imask

一組標志位標明該結構體中那些成員變量中的值有效。它的意義和上面我們提到的LV_COLUMN型結構體中向對應的成員變量基本相同。更詳細的信息,可以查詢WIN32 API 手冊。

iItem

該結構體代表的項目的索引號。索引號是從0開始編號的。該值和表單的“行”類似。

iSubItem

和上一個成員變量指定的項目相連的子項目的索引號。您可以把它當作表單的“列”。譬如您想要把一個項目插入到新創建的列表視圖控件,iItem的值應為0(因為該項目是第一個項目),iSubItem的值也應當為0(我們想把該項目插到第一列)。如果你想指定一個子項目和該項目相連,iItem中應該是您想要相連的項目的索引號,iSubItem的值應當是大于0的值,具體的值取決于您想把該子項目插在那一列。如果你的列表視圖控件一共有4列的化,第一列包含了項目,其余3列是留給子項目的。如果您想把子項目插在第四列,應當指定該值為3。

state

該成員變量包含的標志位反應了項目的狀態。狀態的改變可能是由用戶的操作引起的或是程序改變的。這些狀態包括:是否有焦點/高亮度顯示/被選中(由于被剪切)/被選中等。另外還包括,以1為基數的索引用來代表是否處使用重疊/狀態圖標。

stateMask

由于上面的成員變量包含狀態標志位、重疊的位圖索引號、和狀態位圖的索引號,我們需要告訴WINDOWS我們到底需要設定或查詢那一個值。該成員變量就是用來做這項工作的。

pszText

當我們想設定項目的屬性時,它包含項目名稱的ASCII碼的字符串的地址。當查詢項目的屬性時,該成員變量將用來接收查詢返回的項目的名稱。

cchTextMax

僅當您用來查詢項目的屬性時才需要使用該值,這時它包含上一個成員變量的大小。

iImage

圖標在列表視圖中的圖象鏈表中的索引號。

lParam

用戶定義的值,當您給項目排序時使用。當您告訴列表視圖對項目排序時,列表視圖將成對地比較項目。 它將會把兩個項目的lParam的值傳給您,這樣您就可以進行比較先列出那一個了。如果您現在還不太明白的話,沒有系,我們稍后還要講關于排序的問題。

現在讓我們來總結想列表控件中插入項目/子項目的步驟:

定義一個LV_ITEM型的結構體變量。

給該變量賦給合適的值

如果要插入一個項目,就向列表視圖控件發送LVM_INSERTITEM值。 如果要插入一個子項目,發送LVM_SETITEM。如果您不明白項目和子項目之間的關系的話,可能會有一些疑惑。子項目僅是項目的屬性而已,也就是說您可以插入一個項目但是不能插入一個子項目。所以添加一個子項目十只能發送LVM_SETITEM消息而不能發送LVM_INSERTITEM消息。

列表視圖控件的消息/通知

既然您知道了如何創建和往其中添加內容,下一步就是如何和它通訊。列表視圖控件和它的父窗口之間的通訊是通過消息/通知來進行的。父窗口通過發送消息來控制列表視圖控件,列表視圖控件通過發送WM_NOTIFY消息來通知它的父窗口。這一點和其它的通用控件沒有什么不同。

排序項目/子項目

您可以在調用CreateWindowEx函數時指定LVS_SORTASCENDING 或 LVS_SORTDESCENDING風格來指定缺省的排序方式。這兩種風格僅僅排序項目的名稱。如果想要排序項目的其它屬性,您可以通過發送LVM_SORTITEMS消息來完成

LVM_SORTITEMS

wParam = lParamSort

lParam = pCompareFunction

lParamSort用戶定義的值,該值將傳遞給用來比較的函數。

pCompareFunction 用戶定義的用來比較排序的函數的地址。該函數的原型如下:

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

lParam1 和 lParam2 是 LV_ITEM型的結構體中的成員變量lParam的值。

lParamSort 是發送LVM_SORTITEMS消息時參數wParam中的值

當列表視圖控件接收到LVM_SORTITEMS消息時,當需要比較項目時它會調用在lParam中指定的比較函數。比較函數將決定那一個項目排在前面。方法很簡單:如果函數返回一個負值,由(lParam代表的)第一個項目排在前,如果返回正值,第二個項目排在前。如果相等,必須返回0 。

真正使得該方法能夠運行的是LV_ITEM型結構體中的成員變量lParam值。當您需要排序時(譬如當您點擊列的標題條時),您需要考慮好排序方案。在本例中,我們把項目的索引放到該成員變量中,這樣我們可以通過發送LVM_GETITEM消息來得到項目的其它信息。注意:當項目重排序后,它們的索引也就變了。所以當重排序后,我需要在lParam參數中反應出新的索引。如果您想在用戶點擊列的標題條時重新排序,您需要在您的窗口過程函數中處理LVN_COLUMNCLICK通知消息。LVN_COLUMNCLICK消息是隨同WM_NOTIFY消息一起發送的。

例子:

該例子創建了一個列表視圖控件,并在其中顯示了當前文件夾中的文件大小和文件名。缺省的視圖是報告方式的,如果您點擊列標題條,標題將按升/降序重新排列。您可以通過菜單選擇不同的顯示方式(大圖標、小圖標等)。當您雙擊一個項目時,項目的名稱將顯示在一個對話框中。

.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

分析:

當主窗口創建后要做的第一件事是創建一個列表視圖控件應用程序。

.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

我們調用CreateWindowEx來創建窗口,并把窗口類的名稱“SysListView32”傳給它。缺省的顯示方式是報告方式,因為您指定了LVS_REPORT標志作為它的風格。

invoke InsertColumn

創建列表視圖控件后,我們向其中插入列。

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

我們指定第一列的寬度和列的標題條,為了在該列中顯示文件的名稱,我們需要在LV_COLUMN 型結構體變量的成員變量iMask中設定標志位LVCF_TEXT 或 LVCF_WIDTH。我們設定pszText為列標題條文本字符串的值,lx設定為列的寬度(以像素點為單位)。然后我們發送LVM_INSERTCOLUMN消息給列表視圖控件,并把該結構體變量傳遞給它。

or lvc.imask,LVCF_FMT

mov lvc.fmt,LVCFMT_RIGHT

插入完第一列后,我們再插入第二列,單擊該列的標題條可以按文件的大小排序。因為我們需要右對齊文本,我們需要在成員變量fmt中指定標志位LVCFMT_RIGHT。我們還必須在成員變量iMask中除了標志位LVCF_TEXT 和 LVCF_WIDTH外還需要指定標志位LVCF_FMT。

mov lvc.pszText,offset Heading2

mov lvc.lx,100

invoke SendMessage,hList, LVM_INSERTCOLUMN, 1 ,addr lvc

剩余的代碼比較簡單。在pszText中放入文本字符串的地址,在lx中放入列的寬度。然后發送消息LVM_INSERTCOLUMN 給列表視圖控件,在參數中同時傳遞列號和結構體變量的地址。

當插入完列后,我們向列表控件中加入項目。

invoke FillFileInfo

FillFileInfo 的代碼如下:

FillFileInfo proc uses edi

LOCAL finddata:WIN32_FIND_DATA

LOCAL FHandle:DWORD

invoke FindFirstFile,addr FileNamePattern,addr finddata

我們調用FindFirstFile來得到第一個符合搜索標準的的文件的信息。FindFirstFile函數的原型如下

FindFirstFile proto pFileName:DWORD, pWin32_Find_Data:DWORD

pFileName 是用來匹配搜索的文件名的地址。該字符串包含了通配符。在我們的例子中是*.*,這樣會搜索當前文件夾中所有的文件。

pWin32_Find_Data 是WIN32_FIND_DATA 型的結構體變量的地址,WIN32_FIND_DATA型的結構體變量將用來保存返回的文件的信息。

如果沒有找到匹配的文件,該函數將在eax中返回INVALID_HANDLE_VALUE 。否則將返回一個搜索句柄,您可以用該句柄在FindNextFile函數中來搜索下一個符合條件的文件。

.if eax!=INVALID_HANDLE_VALUE

mov FHandle,eax

xor edi,edi

如果找到了一個文件,我們在一個變量中保存搜索句柄,并把寄存器edi清零,該寄存器將用作項目的索引號。

.while eax!=0

test finddata.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY

.if ZERO?

在本課中,我們將不處理文件夾,所以我們檢查dwFileAttributes成員變量的值是否有FILE_ATTRIBUTE_DIRECTORY 標志,如果有,我們就忽略掉它,然后調用FindNextFile。

invoke ShowFileInfo,edi, addr finddata

inc edi

.endif

invoke FindNextFile,FHandle,addr finddata

.endw

我們調用ShowFileInfo函數包文件的名稱和大小信息加到列表視圖控件中去。然后讓edi寄存器加一來增加項目的行號。最后我們調用FindNextFile函數在當前文件夾中繼續搜索文件一直到該函數返回0為止(這意味著沒有可供搜索的文件了)。

invoke FindClose,FHandle

.endif

ret

FillFileInfo endp

當前文件夾中的文件枚舉完畢后,我們必須關閉搜索句柄。

先在我們看一下ShowFileInfo函數。該函數由兩個參數,一個是項目的索引號(也即行號),另一個是WIN32_FIND_DATA型結構體變量的地址。

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

把WIN32_FIND_DATA 型結構體變量的值放到寄存器edi中。

mov lvi.imask,LVIF_TEXT+LVIF_PARAM

push row

pop lvi.iItem

mov lvi.iSubItem,0

我們將傳遞項目的名稱和lParam的值,所以我們在iMask中放入標志位LVIF_TEXT 和LVIF_PARAM。接下來我們在iItem中放入傳遞進來的行號,另外由于這是主項目我們必須設置iSubItem的值等于0。

lea eax,[edi].cFileName

mov lvi.pszText,eax

push row

pop lvi.lParam

我們現在要把標簽字符串的地址,在這里也就是WIN32_FIND_DATA 型結構體變量中的文件的名稱放到pszText中。由于我們要完成對項目的排序,所以必須設置lParam的值,我把它設成行號值,這樣我們可以根據索引值來查詢項目。

invoke SendMessage,hList, LVM_INSERTITEM,0, addr lvi

設置完所有LV_ITEM型變量中的值后,我們發送LVM_INSERTITEM消息給列表視圖控件來把項目插入到其中。

mov lvi.imask,LVIF_TEXT

inc lvi.iSubItem

invoke wsprintf,addr buffer, addr template,[edi].nFileSizeLow

lea eax,buffer

mov lvi.pszText,eax

我們將把子項目插入到第二列。一個子項目只能有一個標簽。這樣我們在iMask中指定LVIF_TEXT標志位。接著我們指定子項目所在的列,本例中我們通過將iSubItem加一使得該值等于1。標簽值是文件的大小,為了轉換成文本我們調用wsprintf函數,然后把文本的地址放到pszText中去。

invoke SendMessage,hList,LVM_SETITEM, 0,addr lvi

assume edi:nothing

ret

ShowFileInfo endp

當LV_ITEM型變量中的值設定好之后,我們向列表視圖控件發送LVM_SETITEM消息,并一同把LV_ITEM變量的地址傳過去。注意:發送的消息是LV_ITEM而不是LVM_INSERTITEM,因為我們插入的是子項目,子項目不是真正的項目而是主項目的屬性。所以我們這時是在設定項目的屬性,而不是加入一個項目。

當所有的項目都插入到列表視圖控件后,我們設定它的文本和背景顏色。

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

我們用RGB(R---Red G---Green B---Blue)來把三色轉換并放到eax中。我們通過發送LVM_SETTEXTCOLOR 和 LVM_SETTEXTBKCOLOR 消息來設定文本的前景和背景色。

invoke GetMenu,hWnd

mov hMenu,eax

invoke CheckMenuRadioItem,hMenu,IDM_ICON,IDM_LIST, IDM_REPORT,MF_CHECKED

我們將讓用戶通過菜單來選擇它想要的顯示方式。這樣我們必須先得到菜單的句柄。我了讓用戶跟蹤當前的視圖,我們在菜單中放入一組單選按鈕。我們可以調用CheckMenuRadioItem函數,該函數將把一個單選按鈕放到一個菜單項前。

注意我們創建列表視圖控件時把它的寬度和高度都設成為0。當父窗口改變大小時,它將同時改變大小。這樣我們可以讓列表視圖總是隨著主窗口改變。子我們的例子中,我們讓列表視圖填充整個客戶區。

.elseif uMsg==WM_SIZE

mov eax,lParam

mov edx,eax

and eax,0ffffh

shr edx,16

invoke MoveWindow,hList, 0, 0, eax,edx,TRUE

當父窗口接收到了WM_SIZE消息后,lParam的底字部分包含了客戶區新的寬和高。讓后我們調用MoveWindow來改變列表視圖控件的大小使得它覆蓋整個的客戶區。

當用戶通過菜單選擇了一種選擇方式,我們必須相應地改變列表視圖中的顯示方式。我們調用SetWindowLong函數來設定新的風格。

.elseif uMsg==WM_COMMAND

.if lParam==0

invoke GetWindowLong,hList,GWL_STYLE

and eax,not LVS_TYPEMASK

首先得到當前的風格,然后清除舊的風格。LVS_TYPEMASK 是LVS_ICON+LVS_SMALLICON+LVS_LIST+LVS_REPORT四種風格的集合。這樣當我們用當前的風格“與”“not LVS_TYPEMASK”就等于清除了當前的顯示風格。

在設計菜單時,我們使用了一些小技巧。我們包顯示風格的常數串當作菜單的ID號。

IDM_ICON equ LVS_ICON

IDM_SMALLICON equ LVS_SMALLICON

IDM_LIST equ LVS_LIST

IDM_REPORT equ LVS_REPORT

這樣當父窗口接收到WM_COMMAND消息時,希望顯示的風格值會當成菜單的ID號傳遞過來。

mov edx,wParam

and edx,0FFFFh

在wParam中的低字部分是欲顯示的風格,我們所需要做的只是把高字部分清0。

push edx

or eax,edx

我們把希望顯示的風格加到列表視圖的風格中去(已經去除了舊的風格)。

invoke SetWindowLong,hList,GWL_STYLE,eax

調用SetWindowLong函數來設定新的風格。

pop edx

invoke CheckMenuRadioItem,hMenu,IDM_ICON,IDM_LIST, edx,MF_CHECKED

.endif

我們需要在被選擇的顯示方式前放入單選按鈕。如果要排序,我們必須處理WM_NOTIFY消息。

.elseif uMsg==WM_NOTIFY

push edi

mov edi,lParam

assume edi:ptr NMHDR

mov eax,[edi].hwndFrom

.if eax==hList

當我們接收到了WM_NOTIFY 消息后,lParam包含了指向NMHDR型結構體變量的指針。我們通過把列表視圖控件的值和NMHDR型結構體變量中的hwndFrom成員變量的值比較來判斷,如果相等的話我們就可以確定消息是列表視圖控件發送的。

.if [edi].code==LVN_COLUMNCLICK

assume edi:ptr NM_LISTVIEW

如果通知消息是列表視圖控件發送的,我們檢測該消息是否是LVN_COLUMNCLICK。如果是,它意味著用戶點擊了列標題條。在接收到LVN_COLUMNCLICK消息后,我們假設lParam參數包含NM_LISTVIEW型結構體變量的指針,NM_LISTVIEW型結構體是NMHDR型結構體的擴展。我們需要知道用戶單擊了那一列,在iSubItem中的值即是列號,列的編號是從0開始的。

.if [edi].iSubItem==1

.if SizeSortOrder==0 || SizeSortOrder==2

在這里iSubItem的值是1,它表示用戶點擊的是第二列,即文件的大小。我們用狀態變量來保持當前的排序順序。0代表不用排序,1代表升序,2代表降序。如果該列中的項目/子項目以前沒有排序或為降序,我們就把它設成升序。

invoke SendMessage,hList,LVM_SORTITEMS,1,addr CompareFunc

我們發送消息LVM_SORTITEMS給列表視圖控件,在wParam中傳遞1,在lParam中傳遞比較函數的參數。注意wParam中的值是用戶定義的,用戶可以按自己的需要來解釋,這里我們把它用作排序的方法。我們先來看看比較函數:

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

列表視圖控件將傳遞需要比較的兩個項目的lParam(LV_ITEM型結構體變量的成員變量)比較函數。您還記得嗎?我們在lParam中放置了醒目的索引號。這樣我們利用這些索引號查詢列表視圖來得到項目信息。我們需要的消息是項目/子項目的標簽文本。為此我們準備好LV_ITEM 型結構體變量并在iMask中設置標志位LVIF_TEXT ,在pszText中設置緩沖區的地址,在cchTextMax中設置緩沖區的大小。

.if SortType==1

mov lvi.iSubItem,1

invoke SendMessage,hList,LVM_GETITEMTEXT,lParam1,addr lvi

如果SortType的值為1或2,我們知道點擊了那一列,1代表根據文件的大小按升序排列所有的項目。2的意思相反。這樣我們指定iSubItem為1(代表文件大小列)然后發送LVM_GETITEMTEXT 消息給列表視圖控件來得到在項目的標簽文本串。

invoke String2Dword,addr buffer

mov edi,eax

調用子定義的String2Dword函數來把字符串轉換成一個DWORD值。它將在eax中返回轉換后的值,我們把它保存在edi中以便以后比較用。

invoke SendMessage,hList,LVM_GETITEMTEXT,lParam2,addr lvi

invoke String2Dword,addr buffer

sub edi,eax

mov eax,edi

對lParam2 中的值做同樣的操作。當我們得到了兩個文件的大小后,就可以比較它們了。比較的規則如下:

如果第一個項目放在前面,在eax中返回一個負值

如果第二個項目放在前面,在eax中返回一個正值

如果相等,在eax中返回0

在我們這里,我們想按升序排列,所以我們只要簡單地將第二個項目的文件大小減去第一個項目的文件大小,然后返回放在eax中的值。

.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

當用戶點擊文件名字列時,我們必須比較文件的名字。我們先得到文件的名字,然后調用lstrcmpi函數來比較,然后只要簡單返回lstrcmpi的值,因為該函數比較使用的規則和我們的相同。

當項目排序后,我們調用UpdateParam函數來更新所有項目的lParam的值來反應出最新的改變。

invoke UpdatelParam

mov SizeSortOrder,1

該函數簡單地枚舉列表視圖中所有的項目并且把它們lParam更新成項目的索引號。

.elseif [edi].code==NM_DBLCLK

invoke ShowCurrentFocus

.endif

如果用戶雙擊某個項目時,我們將顯示一個消息框,上面有該項目的有關標簽值。我們必須檢查NMHDR 中的code值是否是 NM_DBLCLK。如果是,我們就得到它的標簽值并顯示在一個消息框中。

ShowCurrentFocus proc

LOCAL lvi:LV_ITEM

LOCAL buffer[256]:BYTE

invoke SendMessage,hList,LVM_GETNEXTITEM,-1, LVNI_FOCUSED

我們是增么怎么知道某個項目被雙擊的呢?當單擊或雙擊某個項目時,它的狀態被設成“焦點”。即使有多個項目被選中,也僅有一個項目有焦點。我們的工作就是去找到那個有焦點的項目。我們發送LVM_GETNEXTITEM消息給列表視圖控件,在lParam中指定期望的狀態。如果wParam中時-1的話,表示要搜索所有的項目。有焦點的項目第索引號在eax中返回。

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

發送LVM_GETITEM消息來得到標簽。

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

最后我們在一個消息框中顯示標簽。

如果想在列表視圖控件中顯示圖標,您可以閱讀關于樹型視圖控件的課程。它們的步驟基本上是一樣的。

總結

以上是生活随笔為你收集整理的linux sort -w32,WIN32汇编: 31.列表视图控件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。