OSDN Git Service

refactor
[winmerge-jp/winmerge-jp.git] / Src / IListCtrlImpl.h
1 #pragma once\r
2 \r
3 #include "IListCtrl.h"\r
4 #include <commctrl.h>\r
5 #include <atlimage.h>\r
6 \r
7 struct ListViewOwnerDataItem\r
8 {\r
9     LPARAM lParam;\r
10     int iIndent;\r
11     int iImage;\r
12 };\r
13 \r
14 class IListCtrlImpl : public IListCtrl\r
15 {\r
16 public:\r
17         explicit IListCtrlImpl(HWND hwndListCtrl, std::vector<ListViewOwnerDataItem>& listViewItems)\r
18                 : m_hwndListCtrl(hwndListCtrl)\r
19                 , m_listViewItems(listViewItems)\r
20         {\r
21         }\r
22 \r
23         ~IListCtrlImpl() override {}\r
24 \r
25         int GetColumnCount() const override\r
26         {\r
27                 return Header_GetItemCount(ListView_GetHeader(m_hwndListCtrl));\r
28         }\r
29 \r
30         int GetRowCount() const override\r
31         {\r
32                 return static_cast<int>(m_listViewItems.size());\r
33         }\r
34 \r
35         String GetColumnName(int col) const override\r
36         {\r
37                 LVCOLUMN lvc;\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
43                 return lvc.pszText;\r
44         }\r
45 \r
46         String GetItemText(int row, int col) const override\r
47         {\r
48                 tchar_t text[512]; // Assuming max col header will never be > 512\r
49                 text[0] = '\0';\r
50                 ListView_GetItemText(m_hwndListCtrl, row, col, text, sizeof(text)/sizeof(text[0]));\r
51                 return text;\r
52         }\r
53 \r
54         void *GetItemData(int row) const override\r
55         {\r
56                 if (row < 0 || row >= static_cast<int>(m_listViewItems.size()))\r
57                         return nullptr;\r
58                 return reinterpret_cast<void *>(m_listViewItems[row].lParam);\r
59         }\r
60 \r
61         int GetTextColor(int row) const override\r
62         {\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
71         }\r
72 \r
73         int GetBackColor(int row) const override\r
74         {\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
83         }\r
84 \r
85         bool IsSelectedItem(int sel) const override\r
86         {\r
87                 return !!ListView_GetItemState(m_hwndListCtrl, sel, LVIS_SELECTED);\r
88         }\r
89 \r
90         int GetNextItem(int sel, bool selected = false, bool reverse = false) const override\r
91         {\r
92                 if (!reverse)\r
93                         return ListView_GetNextItem(m_hwndListCtrl, sel, (selected ? LVNI_SELECTED : 0));               \r
94                 if (!selected)\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
98                 {\r
99                         if (ListView_GetItemState(m_hwndListCtrl, i, LVIS_SELECTED))\r
100                                 return i;\r
101                 }\r
102                 return -1;\r
103         }\r
104 \r
105         int GetNextSelectedItem(int sel, bool reverse = false) const override\r
106         {\r
107                 return GetNextItem(sel, true, reverse);\r
108         }\r
109 \r
110         unsigned GetSelectedCount() const override\r
111         {\r
112                 return ListView_GetSelectedCount(m_hwndListCtrl);\r
113         }\r
114 \r
115         int GetIndent(int row) const override\r
116         {\r
117                 LVITEM item = {0};\r
118                 item.mask = LVIF_INDENT;\r
119                 item.iItem = row;\r
120                 ListView_GetItem(m_hwndListCtrl, &item);\r
121                 return item.iIndent;\r
122         }\r
123 \r
124         int GetIconIndex(int row) const override\r
125         {\r
126                 LVITEM item = {0};\r
127                 item.mask = LVIF_IMAGE;\r
128                 item.iItem = row;\r
129                 ListView_GetItem(m_hwndListCtrl, &item);\r
130                 return item.iImage;\r
131         }\r
132 \r
133         int GetIconCount() const override\r
134         {\r
135                 HIMAGELIST hImageList = ListView_GetImageList(m_hwndListCtrl, LVSIL_SMALL);\r
136                 return ImageList_GetImageCount(hImageList);\r
137         }\r
138 \r
139         std::string GetIconPNGData(int iconIndex) const override\r
140         {\r
141                 HIMAGELIST hImageList = ListView_GetImageList(m_hwndListCtrl, LVSIL_SMALL);\r
142                 IMAGEINFO imageInfo;\r
143                 std::string ret;\r
144                 if (ImageList_GetImageInfo(hImageList, iconIndex, &imageInfo))\r
145                 {\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
151                         void *pBits;\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
159                         {\r
160                                 HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcMem, hbmpImage);\r
161                                 ImageList_Draw(hImageList, iconIndex, hdcMem, 0, 0, ILD_TRANSPARENT);\r
162                                 CImage image;\r
163                                 image.Attach(hbmpImage);\r
164                                 image.SetHasAlphaChannel(true);\r
165                                 IStream *pStream = nullptr;\r
166                                 if (SUCCEEDED(CreateStreamOnHGlobal(nullptr, TRUE, &pStream)))\r
167                                 {\r
168                                         image.Save(pStream, Gdiplus::ImageFormatPNG);\r
169                                         STATSTG stat;\r
170                                         if (SUCCEEDED(pStream->Stat(&stat, STATFLAG_NONAME)))\r
171                                         {\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
176                                         }\r
177                                         pStream->Release();\r
178                                 }\r
179                                 SelectObject(hdcMem, hbmpOld);\r
180                                 DeleteObject(hdcMem);\r
181                                 DeleteObject(hbmpImage);\r
182                         }\r
183                 }\r
184                 return ret;\r
185         }\r
186 \r
187 protected:\r
188         HWND m_hwndListCtrl;\r
189         std::vector<ListViewOwnerDataItem>& m_listViewItems;\r
190 };\r