前段時間寫一個虛擬桌面的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;
}
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中的描述:
iSubItemType: 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