1.前言
公司的一个需求要实现界面上直接编辑列表实现对内容的保存,mfc的相关资料较多,直接使用win32没有,参考了mfc的相关方法,给出解决方案
2.解决
代码片段
INT_PTR CALLBACK MainWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hlist, hsublist;
static HFONT hFont;
static int snitem = -1, snsubitem = -1;
static std::map<int, std::wstring> mapIndexValue;
auto setlistvalue = [&](){
if (snitem >= 0 && snsubitem >= 0)
{
TCHAR ptBuf[MAX_PATH] = {0};
GetDlgItemText(hDlg, IDC_EDIT1, ptBuf, MAX_PATH);
ListView_SetItemText(hsublist, snitem, snsubitem, ptBuf);
SetDlgItemText(hDlg, IDC_EDIT1, TEXT(""));
mapIndexValue[snsubitem * 1000 + snitem] = ptBuf;
snsubitem = -1;
snitem = -1;
MoveWindow(GetDlgItem(hDlg, IDC_EDIT1), 0, 0, 1, 1, TRUE);
}
};
auto getlistvalue = [&](int nitem, int nsubitem){
if (nitem >= 0 && nsubitem >= 0)
{
std::wstring wstrvalue = mapIndexValue[snsubitem * 1000 + snitem];
SetDlgItemText(hDlg, IDC_EDIT1, wstrvalue.c_str());
}
};
switch (message)
{
case WM_INITDIALOG:
{
LOGFONT lgf;
GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lgf), &lgf);
lgf.lfWeight = FW_THIN;
lgf.lfHeight = 12;
hFont = CreateFontIndirect(&lgf);
SendMessage(GetDlgItem(hDlg, IDC_EDIT1), WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
MoveWindow(GetDlgItem(hDlg, IDC_EDIT1), 0, 0, 1, 1, TRUE);
SetTimer(hDlg, ID_CHEAK_FOCUS, 100, NULL);
return (INT_PTR)TRUE;
}
case WM_TIMER:
{
if (GetFocus() != GetDlgItem(hDlg, IDC_EDIT1))
setlistvalue();
break;
}
case WM_NOTIFY:
{
if (((LPNMHDR) lParam)->hwndFrom == hsublist)
{
switch (((LPNMHDR) lParam)->code)
{
case NM_DBLCLK:
{
setlistvalue();
NMLISTVIEW *nmlv = (NMLISTVIEW *) lParam;
int nselitem = nmlv->iItem;
int nsubitem = nmlv->iSubItem;
if (nselitem >= 0 && nsubitem >= 0)
{
snitem = nselitem;
snsubitem = nsubitem;
getlistvalue(nselitem, nsubitem);
RECT rtItem;
ListView_GetItemRect(hsublist, nselitem, &rtItem, LVIR_BOUNDS);
POINT ptBeg;
ptBeg.x = rtItem.left + 25 + (nsubitem - 1) * 98;
ptBeg.y = rtItem.top;
ClientToScreen(hsublist, &ptBeg);
ScreenToClient(hDlg, &ptBeg);
MoveWindow(GetDlgItem(hDlg, IDC_EDIT1), ptBeg.x, ptBeg.y, 98, rtItem.bottom - rtItem.top, TRUE);
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
}
break;
}
}
}
break;
}
case WM_CLOSE:
{
KillTimer(hDlg, ID_CHEAK_FOCUS);
DeleteObject(hFont);
break;
}
}
return (INT_PTR)FALSE;
}
备注:基本思路都一样,获取列表的单击事件后进行文本框位置移动和覆盖,这里使用计时器来实现当文本框失去焦点时,进行列表的赋值