• 0

[C++] ListView


Question

I'm having some problems getting a listview to behave properly

Using the following styles I get the following:

LVS_EX_CHECKBOXES | HDS_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP

post-51082-1252028925.png

Problems:

- No checkbox in header

- Clicking on rows does not tick/untick the checkboxes, you need to click on the checkbox itself

The style of row selection also isn't the one i'd like, I'd really like row highlighting like in vlc > preferences > hotkeys, e.g.:

post-51082-1252027290.png

Upon adding the LVS_EX_AUTOCHECKSELECT style:

post-51082-1252027623.png

The checkbox in header now appears, HDS_CHECKBOXES had no effect.

Clicking on a row ticks the checkbox - good

However, problems:

- Clicking again on a row does not untick a checkbox. Should I forget this style and hard code it myself by detecting click events...?

- ****BIG PROBLEM**** The check boxes have all disappeared. They reappear for a single row when hovering over that row. If you tick a checkbox, and move away from the row, the checkbox disappears, moving back it reappears, but unticked. If you select a row, the ticked checkbox remains visible and ticked, until you select another row.

I could really do with some pointers on how to fix this, there are too many variables from my point of view :(

Some code:

this->hListViews[0] = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, _T(""),  LVS_REPORT | WS_CHILD | WS_VISIBLE, 15, 17, 264, 260, this->hwnd, (HMENU)ID_CTRL_LNKPPL_LV, GetModuleHandle(NULL), NULL);

SendMessage(this->hListViews[0], LVM_SETEXTENDEDLISTVIEWSTYLE, (WPARAM)(DWORD) LVS_EX_CHECKBOXES | HDS_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP | LVS_EX_AUTOCHECKSELECT, (LPARAM)(DWORD) LVS_EX_CHECKBOXES | HDS_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP | LVS_EX_AUTOCHECKSELECT); // extended styles (must be sent as a message!)

LVCOLUMN col1, col2, col3;
col1.fmt = col2.fmt = col3.fmt = LVCFMT_LEFT;
col1.mask = LVCF_FMT | LVCF_WIDTH;
col2.mask = col3.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
col1.cx = 30;
col2.cx = 40;
col3.cx = 172;
col2.pszText = LinkPeopleWindow::colHeaders[0];
col3.pszText = LinkPeopleWindow::colHeaders[1];
ListView_InsertColumn(this->hListViews[0], 0, &col1);
ListView_InsertColumn(this->hListViews[0], 1, &col2);
ListView_InsertColumn(this->hListViews[0], 2, &col3);

// Populate list view
LVITEM *items[20];
for (int i=0; i < 20; i++) {
	items[i] = new LVITEM;
	items[i]->mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
	items[i]->iItem = i;
	items[i]->iSubItem = 0;
	items[i]->state = 0; 
	items[i]->stateMask = 0;
	items[i]->lParam = (LPARAM) &LinkPeopleWindow::tmp;
	items[i]->pszText = LPSTR_TEXTCALLBACK; // sends an LVN_GETDISP message.
	SendMessage(this->hListViews[0], LVM_INSERTITEM, (WPARAM)0, (LPARAM)items[i]);
}

class LinkPeopleWindow
{
public:
static TCHAR* tmp[];
private:
	HWND hListViews[1];			// array of listviews
protected:
	static TCHAR* colHeaders[];	// List View column headings (NOTE, can NOT be const, incompatable type for LVCOLUMN pszText!)
};

TCHAR* LinkPeopleWindow::colHeaders[] = { _T("ID"), _T("Name") }; //NOTE, can NOT be const, incompatable type for LVCOLUMN pszText!

TCHAR* LinkPeopleWindow::tmp[] = { _T("a"), _T("1"), _T("Example Example Example Example") };

	case WM_NOTIFY:
		wmId	= LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		switch (wmId)
		{
		case ID_CTRL_LNKPPL_LV:
			switch (((LPNMHDR) lParam)->code)
			{
			case LVN_GETDISPINFO:
				NMLVDISPINFO* plvdi = (NMLVDISPINFO*)lParam;	
				switch (plvdi->item.iSubItem)
				{
				case 0:
					//plvdi->item.pszText = LinkPeopleWindow::tmp[0];
					break;
				case 1:
					plvdi->item.pszText = LinkPeopleWindow::tmp[1];
					break;
				case 2:
					plvdi->item.pszText = LinkPeopleWindow::tmp[2];
					break;
				default:
					break;
				}
				return 0;
			}
			break;
		default:
			break;
		}
		break;

#include <commctrl.h> is present in stdafx.h

InitCommonControls(); in _tWinMain()

ComCtl32.Lib dragged and dropped into project from C:\Program Files\Microsoft SDKs\Windows\v7.0\Lib

Win 7 x64 RTM; VC9 express edition; windows sdk v7 rtm; C++; win32; 32-bit application (currently)

Link to comment
https://www.neowin.net/forum/topic/819824-c-listview/
Share on other sites

4 answers to this question

Recommended Posts

  • 0

After playing around a little more, I get the impression that with LVS_EX_AUTOCHECKSELECT, the checkboxes, from their behaviour, seem to be entirely linked to row selection - select a row, ticked checkbox is visible; select a different row, first looses it's tick; checkbox appears on hover on unticked rows, ticking it selects the row, unticking deselects. multiple row selections are possible (regardless of the LVS_SINGLESEL style). Ticking the checkbox in the header ticks all checkboxes AND selects all rows.

edit: just realised that the checkboxes are supposed to be linked to row selection, that's there purpose in a list-view. They would only be considered data in a datagrid type control. duh.

  code.kliu.org said:
I haven't used checkbox listviews before, so I can't say anything about that, but as for the visual style, you need this. Set hwnd to the handle of your list view (not of its parent window), and pszSubAppName to Explorer.

ah, awesome, got that style implemented perfectly now, cheers ;)

  code.kliu.org said:
PS: To use the HD[sMN]_ styles/messages/notifications, you need to get a separate handle for the header control. You can get that using LVM_GETHEADER.

Ok, i'll look into that if I decide to abandon LVS_EX_AUTOCHECKSELECT

  code.kliu.org said:
PPS: The docs say that setting the state to 0 hides the checkbox...

Yeh, did wonder whether the state might have a role in this. I've done some playing around with the state property but can't get it to do anything. I'm setting stateMask to 61440 (bits 13-16) and state to 4096 or 8192 (bit 13 or 14 respectively, hopefully mapping to image index values of 1 or 2 respectively).

However, when I remove LVS_EX_AUTOCHECKSELECT, I can't get the checkboxes to be ticked by default by playing around with state either...

Also, when state was 0 and I removed LVS_EX_AUTOCHECKSELECT, the checkboxes were all visible, there was no problem...

I'm beginning to think that the disappearing checkboxes are by design rather than something I've done wrong though.

If that's the case then I'm going to abandon LVS_EX_AUTOCHECKSELECT because I don't like it's behaviour - loosing previous selections when not holding down the ctrl key. The only problem then (apart from the checkbox in the header) is getting control over checkbox state...

Edited by theblazingangel
Link to comment
https://www.neowin.net/forum/topic/819824-c-listview/#findComment-591534388
Share on other sites

  • 0

i've had no luck so far creating the checkbox in the header...

HWND hLVHeader = ListView_GetHeader(this-&gt;hListViews[0]);
DWORD headerStyle = GetWindowLongPtr(hLVHeader, GWL_STYLE);
headerStyle |= HDS_CHECKBOXES;
SetWindowLongPtr(hLVHeader, GWL_STYLE, (LONG_PTR)headerStyle);

HDITEM hdi;
Header_GetItem(hLVHeader, 0, (LPHDITEM) &amp;hdi);
hdi.fmt |= HDF_CHECKBOX;
Header_SetItem(hLVHeader, 0, (LPHDITEM) &amp;hdi);
HDITEM hdi2;
Header_GetItem(hLVHeader, 1, (LPHDITEM) &amp;hdi2);
hdi2.fmt |= HDF_CHECKBOX;
Header_SetItem(hLVHeader, 1, (LPHDITEM) &amp;hdi2);

(both blocks tried both before and after column creation code)

Link to comment
https://www.neowin.net/forum/topic/819824-c-listview/#findComment-591534954
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.