3 #include "IListCtrl.h"
\r
4 #include <commctrl.h>
\r
5 #include <atlimage.h>
\r
7 struct ListViewOwnerDataItem
\r
14 class IListCtrlImpl : public IListCtrl
\r
17 explicit IListCtrlImpl(HWND hwndListCtrl, std::vector<ListViewOwnerDataItem>& listViewItems)
\r
18 : m_hwndListCtrl(hwndListCtrl)
\r
19 , m_listViewItems(listViewItems)
\r
23 ~IListCtrlImpl() override {}
\r
25 int GetColumnCount() const override
\r
27 return Header_GetItemCount(ListView_GetHeader(m_hwndListCtrl));
\r
30 int GetRowCount() const override
\r
32 return static_cast<int>(m_listViewItems.size());
\r
35 String GetColumnName(int col) const override
\r
38 tchar_t columnName[256]; // Assuming max col header will never be > 256
\r
39 lvc.mask = LVCF_TEXT;
\r
40 lvc.pszText = &columnName[0];
\r
41 lvc.cchTextMax = sizeof(columnName) / sizeof(tchar_t);
\r
42 ListView_GetColumn(m_hwndListCtrl, col, &lvc);
\r
46 String GetItemText(int row, int col) const override
\r
48 tchar_t text[512]; // Assuming max col header will never be > 512
\r
50 ListView_GetItemText(m_hwndListCtrl, row, col, text, sizeof(text)/sizeof(text[0]));
\r
54 void *GetItemData(int row) const override
\r
56 if (row < 0 || row >= static_cast<int>(m_listViewItems.size()))
\r
58 return reinterpret_cast<void *>(m_listViewItems[row].lParam);
\r
61 int GetTextColor(int row) const override
\r
63 NMLVCUSTOMDRAW nmlvcd = {0};
\r
64 nmlvcd.nmcd.hdr.code = NM_CUSTOMDRAW;
\r
65 nmlvcd.nmcd.hdr.idFrom = GetDlgCtrlID(m_hwndListCtrl);
\r
66 nmlvcd.nmcd.hdr.hwndFrom = m_hwndListCtrl;
\r
67 nmlvcd.nmcd.dwDrawStage = CDDS_ITEMPREPAINT | CDDS_SUBITEM;
\r
68 nmlvcd.nmcd.dwItemSpec = row;
\r
69 SendMessage(GetParent(m_hwndListCtrl), WM_NOTIFY, (WPARAM)m_hwndListCtrl, (LPARAM)&nmlvcd);
\r
70 return nmlvcd.clrText;
\r
73 int GetBackColor(int row) const override
\r
75 NMLVCUSTOMDRAW nmlvcd = {0};
\r
76 nmlvcd.nmcd.hdr.code = NM_CUSTOMDRAW;
\r
77 nmlvcd.nmcd.hdr.idFrom = GetDlgCtrlID(m_hwndListCtrl);
\r
78 nmlvcd.nmcd.hdr.hwndFrom = m_hwndListCtrl;
\r
79 nmlvcd.nmcd.dwDrawStage = CDDS_ITEMPREPAINT | CDDS_SUBITEM;
\r
80 nmlvcd.nmcd.dwItemSpec = row;
\r
81 SendMessage(GetParent(m_hwndListCtrl), WM_NOTIFY, (WPARAM)m_hwndListCtrl, (LPARAM)&nmlvcd);
\r
82 return nmlvcd.clrTextBk;
\r
85 bool IsSelectedItem(int sel) const override
\r
87 return !!ListView_GetItemState(m_hwndListCtrl, sel, LVIS_SELECTED);
\r
90 int GetNextItem(int sel, bool selected = false, bool reverse = false) const override
\r
93 return ListView_GetNextItem(m_hwndListCtrl, sel, (selected ? LVNI_SELECTED : 0));
\r
95 return ListView_GetNextItem(m_hwndListCtrl, sel, LVNI_ABOVE);
\r
96 // It seems that when LVS_OWNERDATA is enabled and LVNI_SELECTED | LVNI_ABOVE is passed to ListView_GetNextItem(), the expected result is not obtained.
\r
97 for (int i = sel - 1; i >= 0; --i)
\r
99 if (ListView_GetItemState(m_hwndListCtrl, i, LVIS_SELECTED))
\r
105 int GetNextSelectedItem(int sel, bool reverse = false) const override
\r
107 return GetNextItem(sel, true, reverse);
\r
110 unsigned GetSelectedCount() const override
\r
112 return ListView_GetSelectedCount(m_hwndListCtrl);
\r
115 int GetIndent(int row) const override
\r
118 item.mask = LVIF_INDENT;
\r
120 ListView_GetItem(m_hwndListCtrl, &item);
\r
121 return item.iIndent;
\r
124 int GetIconIndex(int row) const override
\r
127 item.mask = LVIF_IMAGE;
\r
129 ListView_GetItem(m_hwndListCtrl, &item);
\r
130 return item.iImage;
\r
133 int GetIconCount() const override
\r
135 HIMAGELIST hImageList = ListView_GetImageList(m_hwndListCtrl, LVSIL_SMALL);
\r
136 return ImageList_GetImageCount(hImageList);
\r
139 std::string GetIconPNGData(int iconIndex) const override
\r
141 HIMAGELIST hImageList = ListView_GetImageList(m_hwndListCtrl, LVSIL_SMALL);
\r
142 IMAGEINFO imageInfo;
\r
144 if (ImageList_GetImageInfo(hImageList, iconIndex, &imageInfo))
\r
146 HDC hdcMem = CreateCompatibleDC(nullptr);
\r
147 BITMAPINFO bmpinfo = { 0 };
\r
148 bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
\r
149 int w = imageInfo.rcImage.right - imageInfo.rcImage.left;
\r
150 int h = imageInfo.rcImage.bottom - imageInfo.rcImage.top;
\r
152 bmpinfo.bmiHeader.biWidth = w;
\r
153 bmpinfo.bmiHeader.biHeight = h;
\r
154 bmpinfo.bmiHeader.biPlanes = 1;
\r
155 bmpinfo.bmiHeader.biBitCount = 32;
\r
156 bmpinfo.bmiHeader.biCompression = BI_RGB;
\r
157 HBITMAP hbmpImage = CreateDIBSection(nullptr, &bmpinfo, DIB_RGB_COLORS, &pBits, nullptr, 0);
\r
158 if (hbmpImage != nullptr)
\r
160 HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcMem, hbmpImage);
\r
161 ImageList_Draw(hImageList, iconIndex, hdcMem, 0, 0, ILD_TRANSPARENT);
\r
163 image.Attach(hbmpImage);
\r
164 image.SetHasAlphaChannel(true);
\r
165 IStream *pStream = nullptr;
\r
166 if (SUCCEEDED(CreateStreamOnHGlobal(nullptr, TRUE, &pStream)))
\r
168 image.Save(pStream, Gdiplus::ImageFormatPNG);
\r
170 if (SUCCEEDED(pStream->Stat(&stat, STATFLAG_NONAME)))
\r
172 LARGE_INTEGER li = { 0 };
\r
173 ret.resize(stat.cbSize.LowPart, 0);
\r
174 pStream->Seek(li, STREAM_SEEK_SET, nullptr);
\r
175 pStream->Read(&ret[0], stat.cbSize.LowPart, nullptr);
\r
177 pStream->Release();
\r
179 SelectObject(hdcMem, hbmpOld);
\r
180 DeleteObject(hdcMem);
\r
181 DeleteObject(hbmpImage);
\r
188 HWND m_hwndListCtrl;
\r
189 std::vector<ListViewOwnerDataItem>& m_listViewItems;
\r