void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) { widget->window = CreateWindowEx( WS_EX_CLIENTEDGE, WC_LISTVIEW, L"", WS_CHILD | WS_TABSTOP | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | LVS_NOCOLUMNHEADER, x, y, width, height, parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0 ); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0); ListView_SetExtendedListViewStyle(widget->window, LVS_EX_FULLROWSELECT); lstring list; list.split("\t", text); listBox->columns = list.size(); for(unsigned i = 0; i < list.size(); i++) { LVCOLUMN column; column.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM; column.fmt = LVCFMT_LEFT; column.iSubItem = list.size(); utf16_t text(list[i]); column.pszText = text; ListView_InsertColumn(widget->window, i, &column); } resizeColumnsToContent(); } void ListBox::setHeaderVisible(bool headerVisible) { SetWindowLong( widget->window, GWL_STYLE, (GetWindowLong(widget->window, GWL_STYLE) & ~LVS_NOCOLUMNHEADER) | (headerVisible == false ? LVS_NOCOLUMNHEADER : 0) ); } void ListBox::setCheckable(bool checkable) { ListView_SetExtendedListViewStyle(widget->window, LVS_EX_FULLROWSELECT | (checkable ? LVS_EX_CHECKBOXES : 0)); } void ListBox::reset() { ListView_DeleteAllItems(widget->window); } void ListBox::resizeColumnsToContent() { for(unsigned i = 0; i < listBox->columns; i++) { ListView_SetColumnWidth(widget->window, i, LVSCW_AUTOSIZE_USEHEADER); } } void ListBox::addItem(const string &text) { lstring list; list.split("\t", text); LVITEM item; unsigned row = ListView_GetItemCount(widget->window); item.mask = LVIF_TEXT; item.iItem = row; item.iSubItem = 0; utf16_t wtext(list[0]); item.pszText = wtext; object->locked = true; ListView_InsertItem(widget->window, &item); object->locked = false; for(unsigned i = 1; i < list.size(); i++) { utf16_t wtext(list[i]); ListView_SetItemText(widget->window, row, i, wtext); } //workaround: when there is only one column, the horizontal scrollbar will always appear without this if(listBox->columns == 1) ListView_SetColumnWidth(widget->window, 0, LVSCW_AUTOSIZE_USEHEADER); } void ListBox::setItem(unsigned row, const string &text) { lstring list; list.split("\t", text); for(unsigned i = 0; i < list.size(); i++) { utf16_t wtext(list[i]); ListView_SetItemText(widget->window, row, i, wtext); } //workaround: when there is only one column, the horizontal scrollbar will always appear without this if(listBox->columns == 1) ListView_SetColumnWidth(widget->window, 0, LVSCW_AUTOSIZE_USEHEADER); } optional ListBox::selection() { unsigned count = ListView_GetItemCount(widget->window); for(unsigned i = 0; i < count; i++) { if(ListView_GetItemState(widget->window, i, LVIS_SELECTED)) return { true, i }; } return { false, 0 }; } void ListBox::setSelection(unsigned row) { unsigned count = ListView_GetItemCount(widget->window); for(unsigned i = 0; i < count; i++) { ListView_SetItemState(widget->window, i, LVIS_FOCUSED, (i == row ? LVIS_FOCUSED : 0)); ListView_SetItemState(widget->window, i, LVIS_SELECTED, (i == row ? LVIS_SELECTED : 0)); } } bool ListBox::checked(unsigned row) { return ListView_GetCheckState(widget->window, row); } void ListBox::setChecked(unsigned row, bool checked) { object->locked = true; ListView_SetCheckState(widget->window, row, checked); object->locked = false; } ListBox::ListBox() { listBox = new ListBox::Data; listBox->lostFocus = false; }