主题:[原创]分享可编辑ListView的实现
标准的ListView控件只有标题列(第一列)可编辑,其他列的编辑需要自己用一个EDIT控件来模拟。实现的原理和过程如下:
(1)鼠标双击时,创建并初始化编辑框,选中编辑框中的内容;
(2)编辑框失去焦点或回车键确认修改后,保存修改后的内容,销毁编辑框;
(3)Esc键取消修改后,不保存修改后的内容,直接销毁编辑框。
WNDPROC oldListViewWndProc,oldListEditWndProc;
//listview控件子类化过程
LRESULT CALLBACK ListViewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static LVHITTESTINFO lvi;
static HWND hEditWnd;
TCHAR text[256];
HDITEM hdi;
RECT rect;
switch(uMsg)
{
case WM_LBUTTONDBLCLK:
lvi.pt.x = LOWORD(lParam);
lvi.pt.y = HIWORD(lParam);
ListView_SubItemHitTest(hwnd,&lvi);
if(lvi.iItem!=-1&&lvi.iSubItem!=-1)
{
hdi.mask = HDI_LPARAM;
Header_GetItem(ListView_GetHeader(hwnd),lvi.iSubItem,&hdi);
if(hdi.lParam>0)//该列可编辑
{
ListView_GetSubItemRect(hwnd,lvi.iItem,lvi.iSubItem,LVIR_BOUNDS,&rect);
ListView_GetItemText(hwnd,lvi.iItem,lvi.iSubItem,text,sizeof(text)/sizeof(TCHAR)-1);
hEditWnd = CreateWindow(TEXT("EDIT"),text,WS_CHILD|WS_VISIBLE,rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top,hwnd,NULL,GetModuleHandle(NULL),NULL);
SetWindowLong(hEditWnd,GWL_USERDATA,1);
oldListEditWndProc = (WNDPROC)SetWindowLong(hEditWnd,GWL_WNDPROC,(LONG)ListEditWndProc);
SendMessage(hEditWnd,WM_SETFONT,(WPARAM)SendMessage(hwnd,WM_GETFONT,0,0),0);
SetFocus(hEditWnd);
SendMessage(hEditWnd,EM_SETSEL,0,(LPARAM)-1);
}
}
break;
case WM_COMMAND:
if(HIWORD(wParam)!=EN_KILLFOCUS) break;
case WM_MOUSEACTIVATE:
if(hEditWnd)
{
if(GetWindowLong(hEditWnd,GWL_USERDATA))
{
GetWindowText(hEditWnd,text,sizeof(text)/sizeof(TCHAR)-1);
if(text[0])
{
ListView_SetItemText(hwnd,lvi.iItem,lvi.iSubItem,text);
}
}
DestroyWindow(hEditWnd);
hEditWnd = NULL;
}
break;
}
return CallWindowProc(oldListViewWndProc,hwnd,uMsg,wParam,lParam);
}
//Edit控件子类化过程
LRESULT CALLBACK ListEditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LPMSG lpmsg;
switch(uMsg)
{
case WM_GETDLGCODE:
lpmsg = (LPMSG)lParam;
if(lpmsg)
{
switch(lpmsg->message)
{
case WM_KEYDOWN:
switch(lpmsg->wParam)
{
case VK_SPACE://空格键转为跳格键
lpmsg->wParam = VK_TAB;
case VK_TAB:
return DLGC_WANTTAB;//屏蔽跳格键
case VK_ESCAPE://撤销修改
SetWindowLong(hwnd,GWL_USERDATA,0);
case VK_RETURN://确认修改
SetFocus(GetParent(hwnd));
return DLGC_WANTALLKEYS;
}
break;
}
}
break;
//阻止WM_MOUSEACTIVATE消息传递到父窗口
case WM_MOUSEACTIVATE:
return MA_ACTIVATE;
//阻止WM_MOUSEWHEEL消息传递到父窗口
case WM_MOUSEWHEEL:
return 0;
}
return CallWindowProc(oldListEditWndProc,hwnd,uMsg,wParam,lParam);
}
(1)鼠标双击时,创建并初始化编辑框,选中编辑框中的内容;
(2)编辑框失去焦点或回车键确认修改后,保存修改后的内容,销毁编辑框;
(3)Esc键取消修改后,不保存修改后的内容,直接销毁编辑框。
WNDPROC oldListViewWndProc,oldListEditWndProc;
//listview控件子类化过程
LRESULT CALLBACK ListViewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static LVHITTESTINFO lvi;
static HWND hEditWnd;
TCHAR text[256];
HDITEM hdi;
RECT rect;
switch(uMsg)
{
case WM_LBUTTONDBLCLK:
lvi.pt.x = LOWORD(lParam);
lvi.pt.y = HIWORD(lParam);
ListView_SubItemHitTest(hwnd,&lvi);
if(lvi.iItem!=-1&&lvi.iSubItem!=-1)
{
hdi.mask = HDI_LPARAM;
Header_GetItem(ListView_GetHeader(hwnd),lvi.iSubItem,&hdi);
if(hdi.lParam>0)//该列可编辑
{
ListView_GetSubItemRect(hwnd,lvi.iItem,lvi.iSubItem,LVIR_BOUNDS,&rect);
ListView_GetItemText(hwnd,lvi.iItem,lvi.iSubItem,text,sizeof(text)/sizeof(TCHAR)-1);
hEditWnd = CreateWindow(TEXT("EDIT"),text,WS_CHILD|WS_VISIBLE,rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top,hwnd,NULL,GetModuleHandle(NULL),NULL);
SetWindowLong(hEditWnd,GWL_USERDATA,1);
oldListEditWndProc = (WNDPROC)SetWindowLong(hEditWnd,GWL_WNDPROC,(LONG)ListEditWndProc);
SendMessage(hEditWnd,WM_SETFONT,(WPARAM)SendMessage(hwnd,WM_GETFONT,0,0),0);
SetFocus(hEditWnd);
SendMessage(hEditWnd,EM_SETSEL,0,(LPARAM)-1);
}
}
break;
case WM_COMMAND:
if(HIWORD(wParam)!=EN_KILLFOCUS) break;
case WM_MOUSEACTIVATE:
if(hEditWnd)
{
if(GetWindowLong(hEditWnd,GWL_USERDATA))
{
GetWindowText(hEditWnd,text,sizeof(text)/sizeof(TCHAR)-1);
if(text[0])
{
ListView_SetItemText(hwnd,lvi.iItem,lvi.iSubItem,text);
}
}
DestroyWindow(hEditWnd);
hEditWnd = NULL;
}
break;
}
return CallWindowProc(oldListViewWndProc,hwnd,uMsg,wParam,lParam);
}
//Edit控件子类化过程
LRESULT CALLBACK ListEditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LPMSG lpmsg;
switch(uMsg)
{
case WM_GETDLGCODE:
lpmsg = (LPMSG)lParam;
if(lpmsg)
{
switch(lpmsg->message)
{
case WM_KEYDOWN:
switch(lpmsg->wParam)
{
case VK_SPACE://空格键转为跳格键
lpmsg->wParam = VK_TAB;
case VK_TAB:
return DLGC_WANTTAB;//屏蔽跳格键
case VK_ESCAPE://撤销修改
SetWindowLong(hwnd,GWL_USERDATA,0);
case VK_RETURN://确认修改
SetFocus(GetParent(hwnd));
return DLGC_WANTALLKEYS;
}
break;
}
}
break;
//阻止WM_MOUSEACTIVATE消息传递到父窗口
case WM_MOUSEACTIVATE:
return MA_ACTIVATE;
//阻止WM_MOUSEWHEEL消息传递到父窗口
case WM_MOUSEWHEEL:
return 0;
}
return CallWindowProc(oldListEditWndProc,hwnd,uMsg,wParam,lParam);
}