INTRODUCTION AND RELATED INFORMATION:
I am trying to implement a listview control with editable elements and subitems. Instead of simply viewing the list, items and sub-elements should have an edit control, check box, or combo box.
I use raw WinAPI and C++ . I aimed at Windows XP and beyond.
MY EFFORTS TO SOLVE THE PROBLEM:
After researching here and on the Internet, I could only find examples in MFC . They all use the LVN_BEGINLABELEDIT method to implement this behavior.
Unfortunately, I do not completely understand this concept, so I decided to start from scratch (I believe that this is also the best approach to improve programming skills).
MY CONCEPT:
I decided to catch NM_DBLCLK for listview and get the coordinates from there using the macro ListView_GetItemRect or ListView_GetSubItemRect .
Then I would just move the combobox / checkbox / edit control over the corresponding element / subitem (combobox / edit control / checkbox will be created as separate hidden windows).
After the user completes the input (by pressing the enter key or changing the focus), I just hide the combobox / checkbox / edit control.
MY CURRENT RESULTS:
I'm currently tied to the dimensions of the combobox / edit control / check, which is not the same as the dimensions of the element / subitem when moving over the element / subitem.
Question:
Can I improve my code example below to properly adjust the size of the combobox / edit control / checkbox window to the size of the element / subitem? . Now I will focus only on this part of the problem, so that this question is as short as possible.
Here is an instruction for creating a small application that illustrates the problem. Please note that I tried to keep everything as small as possible:
1.) Create the default Win32 project in Visual Studio (I am using VS 2008 ).
2.) Add the following WM_CREATE handler to the main window procedure:
case WM_CREATE: { HWND hEdit = CreateWindowEx( 0,WC_EDIT, L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_CENTER | ES_AUTOHSCROLL, 250, 10, 100, 20, hWnd, (HMENU)1500, hInst, 0 ); HWND hComboBox = CreateWindowEx( 0,WC_COMBOBOX, L"", WS_CHILD | WS_VISIBLE | WS_BORDER | CBS_DROPDOWNLIST, 100, 10, 100, 20, hWnd, (HMENU)1600, hInst, 0 ); HWND hwndLV = CreateWindowEx( 0, WC_LISTVIEW, L"Editable Subitems", WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT | LVS_SINGLESEL, 150, 100, 250, 150, hWnd, (HMENU)2000, hInst, 0 ); // set extended listview styles ListView_SetExtendedListViewStyle( GetDlgItem( hWnd, 2000 ), LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_DOUBLEBUFFER ); // add some columns LVCOLUMN lvc = {0}; lvc.iSubItem = 0; lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvc.fmt = LVCFMT_LEFT; for (long nIndex = 0; nIndex < 5; nIndex++ ) { wchar_t txt[50]; swprintf_s( txt, 50, L"Column %d", nIndex + 1 ); lvc.iSubItem = nIndex; lvc.cx = 60; lvc.pszText = txt; ListView_InsertColumn( GetDlgItem( hWnd,2000 ), nIndex, &lvc ); } // add some items LVITEM lvi; lvi.mask = LVIF_TEXT; lvi.iItem = 0; for( lvi.iItem = 0; lvi.iItem < 10; lvi.iItem++ ) for (long nIndex = 0; nIndex < 5; nIndex++ ) { wchar_t txt[50]; swprintf_s( txt, 50, L"Item %d%d", lvi.iItem + 1, nIndex + 1 ); lvi.iSubItem = nIndex; lvi.pszText = txt; if( ! nIndex ) // item SendDlgItemMessage( hWnd, 2000, LVM_INSERTITEM, 0, reinterpret_cast<LPARAM>(&lvi) ); else // sub-item SendDlgItemMessage( hWnd, 2000, LVM_SETITEM, 0, reinterpret_cast<LPARAM>(&lvi) ); } } return 0L;
3.) Add the following handler for WM_NOTIFY in the main window procedure:
case WM_NOTIFY: { if( ((LPNMHDR)lParam)->code == NM_DBLCLK ) { switch( ((LPNMHDR)lParam)->idFrom ) { case 2000: // remember, this was our listview ID { LPNMITEMACTIVATE lpnmia = (LPNMITEMACTIVATE)lParam; // SHIFT/ALT/CTRL/their combination, must not be pressed if( ( lpnmia->uKeyFlags || 0 ) == 0 ) { // this is where we store item/subitem rectangle RECT rc = { 0, 0, 0, 0 }; if( (lpnmia->iSubItem) <= 0 ) // this is item so we must call ListView_GetItemRect { // this rectangle holds proper left coordinate // since ListView_GetItemRect with LVIR_LABEL flag // messes up rectangle left cordinate RECT rcHelp = { 0, 0, 0, 0 }; // this call gets the length of entire row // but holds proper left coordinate ListView_GetItemRect( lpnmia->hdr.hwndFrom, lpnmia->iItem, &rcHelp, LVIR_BOUNDS ); // this call gets proper rectangle except for the left side ListView_GetItemRect( lpnmia->hdr.hwndFrom, lpnmia->iItem, &rc, LVIR_LABEL ); // now we can correct the left coordinate rc.left = rcHelp.left; } else // it is subitem, so we must call ListView_GetSubItemRect { ListView_GetSubItemRect( lpnmia->hdr.hwndFrom, lpnmia->iItem, lpnmia->iSubItem, LVIR_BOUNDS, &rc ); } // convert listview client coordinates to parent coordinates // so edit control can be properly moved POINT p; px = rc.left; py = rc.top; ClientToScreen( lpnmia->hdr.hwndFrom, &p ); ScreenToClient( hWnd, &p ); MoveWindow( GetDlgItem( hWnd, 1500 ), px, py, rc.right - rc.left, rc.bottom - rc.top, TRUE ); // set focus to our edit control HWND previousWnd = SetFocus( GetDlgItem( hWnd, 1500 ) ); } } break; default: break; } } } break;
And as a result, I get:

You can clearly see that the upper and lower borders of the edit control are not displayed correctly. As for combobox, the width is adjusted correctly, but the height remains unchanged.
I tried replacing the MoveWindow call with SetWindowPos , but the result was the same.
After further intervention, I found that NMITEMACTIVATE errors NMITEMACTIVATE when returning a rectangle of a NMITEMACTIVATE if the listview does not have the LVS_EX_FULLROWSELECT style set. You can see this by simply commenting out the part in my WM_CREATE handler, where I set this style. Perhaps I am doing something wrong, and this βerrorβ may be caused by my code, but I do not see the problem.
EDITED September 17, 2014:
After testing the values ββfor the iItem and iSubItem members of the NMITEMACTIVATE structure, when the listview does not have LVS_EX_FULLROWSELECT , I can verify that the error is not in my code. It always returns iItem equal to 0, regardless of which sub-item I click. This explains the erroneous behavior that I got when deleting this style.
If any additional information is required, leave a comment and I will act as soon as possible.
Thanks for your time and efforts to help.