4 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 typedef struct tagLINE_INFO
39 /*******************************************************************************
40 * Global and Local Variables:
43 static WNDPROC g_orgListWndProc;
44 static DWORD g_columnToSort = ~0UL;
45 static BOOL g_invertSort = FALSE;
46 static LPTSTR g_valueName;
48 #define MAX_LIST_COLUMNS (IDS_LIST_COLUMN_LAST - IDS_LIST_COLUMN_FIRST + 1)
49 static int default_column_widths[MAX_LIST_COLUMNS] = { 200, 175, 400 };
50 static int column_alignment[MAX_LIST_COLUMNS] = { LVCFMT_LEFT, LVCFMT_LEFT, LVCFMT_LEFT };
52 LPCTSTR GetValueName(HWND hwndLV)
54 int item, len, maxLen;
57 if (!g_valueName) g_valueName = HeapAlloc(GetProcessHeap(), 0, 1024);
58 if (!g_valueName) return NULL;
60 maxLen = HeapSize(GetProcessHeap(), 0, g_valueName);
61 if (maxLen == (SIZE_T) - 1) return NULL;
63 item = ListView_GetNextItem(hwndLV, -1, LVNI_FOCUSED);
64 if (item == -1) return NULL;
66 ListView_GetItemText(hwndLV, item, 0, g_valueName, maxLen);
67 len = _tcslen(g_valueName);
68 if (len < maxLen - 1) break;
69 newStr = HeapReAlloc(GetProcessHeap(), 0, g_valueName, maxLen * 2);
70 if (!newStr) return NULL;
78 /*******************************************************************************
79 * Local module support methods
81 static void AddEntryToList(HWND hwndLV, LPTSTR Name, DWORD dwValType, void* ValBuf, DWORD dwCount)
87 linfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LINE_INFO) + dwCount);
88 linfo->dwValType = dwValType;
89 linfo->val_len = dwCount;
90 memcpy(&linfo[1], ValBuf, dwCount);
91 linfo->name = _tcsdup(Name);
93 item.mask = LVIF_TEXT | LVIF_PARAM;
94 item.iItem = 0;/*idx; */
99 item.cchTextMax = _tcslen(item.pszText);
100 if (item.cchTextMax == 0)
101 item.pszText = LPSTR_TEXTCALLBACK;
103 item.lParam = (LPARAM)linfo;
105 /* item.lParam = (LPARAM)ValBuf; */
106 #if (_WIN32_IE >= 0x0300)
110 index = ListView_InsertItem(hwndLV, &item);
112 /* LPTSTR pszText = NULL; */
113 LPTSTR pszText = _T("value");
117 ListView_SetItemText(hwndLV, index, 2, ValBuf);
121 wsprintf(buf, _T("0x%08X (%d)"), *(DWORD*)ValBuf, *(DWORD*)ValBuf);
122 ListView_SetItemText(hwndLV, index, 2, buf);
124 /* lpsRes = convertHexToDWORDStr(lpbData, dwLen); */
128 LPBYTE pData = (LPBYTE)ValBuf;
129 LPTSTR strBinary = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(TCHAR) * 3 + 1);
130 for (i = 0; i < dwCount; i++)
131 wsprintf( strBinary + i*3, _T("%02X "), pData[i] );
132 strBinary[dwCount * 3] = 0;
133 ListView_SetItemText(hwndLV, index, 2, strBinary);
134 HeapFree(GetProcessHeap(), 0, strBinary);
138 /* lpsRes = convertHexToHexCSV(lpbData, dwLen); */
139 ListView_SetItemText(hwndLV, index, 2, pszText);
145 static BOOL CreateListColumns(HWND hWndListView)
151 /* Create columns. */
152 lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
153 lvC.pszText = szText;
155 /* Load the column labels from the resource file. */
156 for (index = 0; index < MAX_LIST_COLUMNS; index++) {
157 lvC.iSubItem = index;
158 lvC.cx = default_column_widths[index];
159 lvC.fmt = column_alignment[index];
160 LoadString(hInst, IDS_LIST_COLUMN_FIRST + index, szText, sizeof(szText)/sizeof(TCHAR));
161 if (ListView_InsertColumn(hWndListView, index, &lvC) == -1) return FALSE;
166 /* OnGetDispInfo - processes the LVN_GETDISPINFO notification message. */
168 static void OnGetDispInfo(NMLVDISPINFO* plvdi)
170 static TCHAR buffer[200];
172 plvdi->item.pszText = NULL;
173 plvdi->item.cchTextMax = 0;
175 switch (plvdi->item.iSubItem) {
177 plvdi->item.pszText = _T("(Default)");
180 switch (((LINE_INFO*)plvdi->item.lParam)->dwValType) {
182 plvdi->item.pszText = _T("REG_SZ");
185 plvdi->item.pszText = _T("REG_EXPAND_SZ");
188 plvdi->item.pszText = _T("REG_BINARY");
191 plvdi->item.pszText = _T("REG_DWORD");
193 case REG_DWORD_BIG_ENDIAN:
194 plvdi->item.pszText = _T("REG_DWORD_BIG_ENDIAN");
197 plvdi->item.pszText = _T("REG_MULTI_SZ");
200 plvdi->item.pszText = _T("REG_LINK");
202 case REG_RESOURCE_LIST:
203 plvdi->item.pszText = _T("REG_RESOURCE_LIST");
206 plvdi->item.pszText = _T("REG_NONE");
209 wsprintf(buffer, _T("unknown(%d)"), plvdi->item.lParam);
210 plvdi->item.pszText = buffer;
215 plvdi->item.pszText = _T("(value not set)");
218 plvdi->item.pszText = _T("");
223 static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
226 l = (LINE_INFO*)lParam1;
227 r = (LINE_INFO*)lParam2;
229 if (g_columnToSort == ~0UL)
232 if (g_columnToSort == 1 && l->dwValType != r->dwValType)
233 return g_invertSort ? (int)r->dwValType - (int)l->dwValType : (int)l->dwValType - (int)r->dwValType;
234 if (g_columnToSort == 2) {
235 /* FIXME: Sort on value */
237 return g_invertSort ? _tcscmp(r->name, l->name) : _tcscmp(l->name, r->name);
240 static void ListViewPopUpMenu(HWND hWnd, POINT pt)
243 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
245 switch (LOWORD(wParam)) {
246 /* case ID_FILE_OPEN: */
254 static LRESULT CALLBACK ListWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
258 if (!_CmdWndProc(hWnd, message, wParam, lParam)) {
259 return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
263 switch (((LPNMHDR)lParam)->code) {
264 case LVN_GETDISPINFO:
265 OnGetDispInfo((NMLVDISPINFO*)lParam);
267 case LVN_COLUMNCLICK:
268 if (g_columnToSort == ((LPNMLISTVIEW)lParam)->iSubItem)
269 g_invertSort = !g_invertSort;
271 g_columnToSort = ((LPNMLISTVIEW)lParam)->iSubItem;
272 g_invertSort = FALSE;
275 ListView_SortItems(hWnd, CompareFunc, hWnd);
278 NMITEMACTIVATE* nmitem = (LPNMITEMACTIVATE)lParam;
281 if (nmitem->hdr.hwndFrom != hWnd) break;
282 /* if (nmitem->hdr.idFrom != IDW_LISTVIEW) break; */
283 /* if (nmitem->hdr.code != ???) break; */
285 switch (nmitem->uKeyFlags) {
286 case LVKF_ALT: /* The ALT key is pressed. */
287 /* properties dialog box ? */
289 case LVKF_CONTROL: /* The CTRL key is pressed. */
290 /* run dialog box for providing parameters... */
292 case LVKF_SHIFT: /* The SHIFT key is pressed. */
296 info.pt.x = nmitem->ptAction.x;
297 info.pt.y = nmitem->ptAction.y;
298 if (ListView_HitTest(hWnd, &info) != -1) {
300 item.mask = LVIF_PARAM;
301 item.iItem = info.iItem;
302 if (ListView_GetItem(hWnd, &item)) {}
310 NM_LISTVIEW* pNm = (NM_LISTVIEW*)lParam;
311 lvH.pt.x = pNm->ptAction.x;
312 lvH.pt.y = pNm->ptAction.y;
313 idx = ListView_HitTest(hWnd, &lvH);
317 ListViewPopUpMenu(hWnd, pt);
324 return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
328 if (wParam == VK_TAB) {
329 /*TODO: SetFocus(Globals.hDriveBar) */
330 /*SetFocus(child->nFocusPanel? child->left.hWnd: child->right.hWnd); */
334 return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
341 HWND CreateListView(HWND hwndParent, int id)
346 /* Get the dimensions of the parent window's client area, and create the list view control. */
347 GetClientRect(hwndParent, &rcClient);
348 hwndLV = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, _T("List View"),
349 WS_VISIBLE | WS_CHILD | LVS_REPORT,
350 0, 0, rcClient.right, rcClient.bottom,
351 hwndParent, (HMENU)id, hInst, NULL);
352 if (!hwndLV) return NULL;
353 ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
355 /* Initialize the image list, and add items to the control. */
357 if (!InitListViewImageLists(hwndLV)) goto fail;
358 if (!InitListViewItems(hwndLV, szName)) goto fail;
360 if (!CreateListColumns(hwndLV)) goto fail;
361 g_orgListWndProc = SubclassWindow(hwndLV, ListWndProc);
364 DestroyWindow(hwndLV);
368 BOOL RefreshListView(HWND hwndLV, HKEY hKey, LPCTSTR keyPath)
370 DWORD max_sub_key_len;
371 DWORD max_val_name_len;
379 if (!hwndLV) return FALSE;
381 SendMessage(hwndLV, WM_SETREDRAW, FALSE, 0);
382 count = ListView_GetItemCount(hwndLV);
383 for (i = 0; i < count; i++) {
384 item.mask = LVIF_PARAM;
386 ListView_GetItem(hwndLV, &item);
387 free(((LINE_INFO*)item.lParam)->name);
388 HeapFree(GetProcessHeap(), 0, (void*)item.lParam);
390 g_columnToSort = ~0UL;
391 ListView_DeleteAllItems(hwndLV);
393 errCode = RegOpenKeyEx(hKey, keyPath, 0, KEY_READ, &hNewKey);
394 if (errCode != ERROR_SUCCESS) return FALSE;
396 /* get size information and resize the buffers if necessary */
397 errCode = RegQueryInfoKey(hNewKey, NULL, NULL, NULL, NULL, &max_sub_key_len, NULL,
398 &val_count, &max_val_name_len, &max_val_size, NULL, NULL);
400 #define BUF_HEAD_SPACE 2 /* FIXME: check why this is required with ROS ??? */
402 if (errCode == ERROR_SUCCESS) {
403 TCHAR* ValName = HeapAlloc(GetProcessHeap(), 0, ++max_val_name_len * sizeof(TCHAR) + BUF_HEAD_SPACE);
404 DWORD dwValNameLen = max_val_name_len;
405 BYTE* ValBuf = HeapAlloc(GetProcessHeap(), 0, ++max_val_size/* + BUF_HEAD_SPACE*/);
406 DWORD dwValSize = max_val_size;
409 /* if (RegQueryValueEx(hNewKey, NULL, NULL, &dwValType, ValBuf, &dwValSize) == ERROR_SUCCESS) { */
410 /* AddEntryToList(hwndLV, _T("(Default)"), dwValType, ValBuf, dwValSize); */
412 /* dwValSize = max_val_size; */
413 while (RegEnumValue(hNewKey, dwIndex, ValName, &dwValNameLen, NULL, &dwValType, ValBuf, &dwValSize) == ERROR_SUCCESS) {
414 ValBuf[dwValSize] = 0;
415 AddEntryToList(hwndLV, ValName, dwValType, ValBuf, dwValSize);
416 dwValNameLen = max_val_name_len;
417 dwValSize = max_val_size;
421 HeapFree(GetProcessHeap(), 0, ValBuf);
422 HeapFree(GetProcessHeap(), 0, ValName);
424 ListView_SortItems(hwndLV, CompareFunc, hwndLV);
425 RegCloseKey(hNewKey);
426 SendMessage(hwndLV, WM_SETREDRAW, TRUE, 0);