您的位置:首页 > 其它

关于windows的list view使用的两点经验

2014-01-14 14:58 267 查看
      前段时间写一个虚拟桌面的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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: