關於windows的list view使用的兩點經驗

      前段時間寫一個虛擬桌面的demo,是使用shell接口以及list展現桌面圖標以及行爲的功能。如圖

實現上包括右鍵菜單的行爲。以下是我在開發過程中碰到的一些難點或者說是不注意就會出錯的地方,花了不少時間找資料測試。

我的程序是基於vs2008的SDK所帶的例子VListvw所做的修改:

C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\winui\controls\common\vlistvw

1. 原程序中在創建list view的時候,使用的style是加了LVS_OWNERDATA;這個風格是基於大數據部分顯示功能使用的,每次顯示數據更新的時候都需要發送LVN_GETDISPINFO消息給控件,讓控件返回顯示的數據。我的程序基於已經存儲下來的數據,不要使用這個風格來獲取信息。應該刪除LVS_OWNERDATA風格。

HWND CreateListView(HINSTANCE hInstance, HWND hwndParent)
{
	DWORD       dwStyle;
	HWND        hwndListView;
	HIMAGELIST  himlSmall;
	HIMAGELIST  himlLarge;
	BOOL        bSuccess = TRUE;

	dwStyle =   WS_TABSTOP | 
				WS_CHILD | 
				WS_BORDER | 
				WS_VISIBLE |
				LVS_AUTOARRANGE |
				LVS_REPORT | 
				LVS_OWNERDATA;
	            
	hwndListView = CreateWindowEx(   WS_EX_CLIENTEDGE,          // ex style
									 WC_LISTVIEW,               // class name - defined in commctrl.h
									 TEXT(""),                        // dummy text
									 dwStyle,                   // style
									 0,                         // x position
									 0,                         // y position
									 0,                         // width
									 0,                         // height
									 hwndParent,                // parent
									 (HMENU)ID_LISTVIEW,        // ID
									 g_hInst,                   // instance
									 NULL);                     // no extra data

	if(!hwndListView)
	   return NULL;

	ResizeListView(hwndListView, hwndParent);

	//set the image lists
	himlSmall = ImageList_Create(16, 16, ILC_COLORDDB | ILC_MASK, 1, 0);
	himlLarge = ImageList_Create(64, 32, ILC_COLORDDB | ILC_MASK, 1, 0);

	if (himlSmall && himlLarge)
	   {
	   HICON hIcon;

	   //set up the small image list
	   hIcon = LoadImage(g_hInst, MAKEINTRESOURCE(IDI_DISK), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
	   ImageList_AddIcon(himlSmall, hIcon);

	   //set up the large image list
	   hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_DISK));
	   ImageList_AddIcon(himlLarge, hIcon);

	   ListView_SetImageList(hwndListView, himlSmall, LVSIL_SMALL);
	   ListView_SetImageList(hwndListView, himlLarge, LVSIL_NORMAL);
	   }

	return hwndListView;
}


2. 另外一個問題,困擾了我幾天,就是在響應右鍵菜單行爲的時候,怎麼樣去獲取已經存儲的那個節點的數據信息。我原來在加入list view的數據的時候,設置了重要的對象信息到LVITEM裏面的lparam這個變量中,但是通過下面的代碼中的ListView_GetItem宏來發送消息取得Item的信息;但是我發現,以下代碼死活無法取得LPARAM變量的值回來。而在處理LVN_GETDISPINFO這個消息的時候,是會傳進去Lparam數據的,但是返回來的時候是沒有的。原則上,已經在lvitem.mask中設置了LVIF_PARAM標記,就會返回LPARAM數據,但是沒有成功!

BOOL DoContextMenu(  HWND hWnd, 
                     WPARAM wParam, 
                     LPARAM lParam)
{
	HWND  hwndListView = (HWND)wParam;
	if(hwndListView != GetDlgItem(hWnd, ID_LISTVIEW))
	   return FALSE;
	POINT p;
	p.x = LOWORD(lParam);
	p.y = HIWORD(lParam);
	::ScreenToClient(hWnd, &p); 
	LVHITTESTINFO lvHittestInfo;
	lvHittestInfo.pt.x = p.x;
	lvHittestInfo.pt.y = p.y;
	int index = ListView_HitTest(hwndListView,&lvHittestInfo);
	if (index<0)
	{
		return FALSE;
	}
	LVITEM lvitem;
	lvitem.mask = LVIF_TEXT|LVIF_PARAM;
	lvitem.iItem = index;
	lvitem.iSubItem = index;
	TCHAR szText[256] = {0};
	lvitem.pszText = szText;
	lvitem.cchTextMax = 256;
	BOOL brc = ListView_GetItem(hwndListView,&lvitem);

	DWORD address = *(DWORD*)(lvitem.pszText); 
	LVITEMDATA *pData = (LVITEMDATA*)(address);
	CShellPidl& pidlParent = pData->pidlAbs;
	if (!pData->IsValid())
		return FALSE;
開始以爲是設置回調函數的問題,經過多次測試,才發現一個重點問題:lvitem.iSubItem!!!

我查一下MSDN中的描述:

iSubItem

Type: int

One-based index of the subitem to which this structure refers, or zero if this structure refers to an item rather than a subitem.

這裏也沒有完全說明白,但試過了之後,就發現,把這個值設置爲0,就可以了!!!在ListView_GetItem的時候也不會發送LVN_GETDISPINFO消息了,返回來的值中帶了Lparam的值!追究起來,這個iSubItem應該是指iItem這一行的一個子項目上附加的數據,這樣一來,即使標記了LVIF_PARAM標誌,也沒法取得對iIem這個項目設置的值了!

附加我的demo程序:http://download.csdn.net/detail/eagleatustb/6847501



發佈了169 篇原創文章 · 獲贊 5 · 訪問量 38萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章