| 1811 | |
| 1812 | |
| 1813 | void ControlGetListView(ResultToken &aResultToken, HWND aHwnd, LPTSTR aOptions) |
| 1814 | // Called by ControlGet() below. It has ensured that aHwnd is a valid handle to a ListView. |
| 1815 | { |
| 1816 | // GET ROW COUNT |
| 1817 | LRESULT row_count; |
| 1818 | if (!SendMessageTimeout(aHwnd, LVM_GETITEMCOUNT, 0, 0, SMTO_ABORTIFHUNG, 2000, (PDWORD_PTR)&row_count)) // Timed out or failed. |
| 1819 | goto error; |
| 1820 | |
| 1821 | // GET COLUMN COUNT |
| 1822 | // Through testing, could probably get to a level of 90% certainty that a ListView for which |
| 1823 | // InsertColumn() was never called (or was called only once) might lack a header control if the LV is |
| 1824 | // created in List/Icon view-mode and/or with LVS_NOCOLUMNHEADER. The problem is that 90% doesn't |
| 1825 | // seem to be enough to justify elimination of the code for "undetermined column count" mode. If it |
| 1826 | // ever does become a certainty, the following could be changed: |
| 1827 | // 1) The extra code for "undetermined" mode rather than simply forcing col_count to be 1. |
| 1828 | // 2) Probably should be kept for compatibility: -1 being returned when undetermined "col count". |
| 1829 | // |
| 1830 | // The following approach might be the only simple yet reliable way to get the column count (sending |
| 1831 | // LVM_GETITEM until it returns false doesn't work because it apparently returns true even for |
| 1832 | // nonexistent subitems -- the same is reported to happen with LVM_GETCOLUMN and such, though I seem |
| 1833 | // to remember that LVM_SETCOLUMN fails on non-existent columns -- but calling that on a ListView |
| 1834 | // that isn't in Report view has been known to traumatize the control). |
| 1835 | // Fix for v1.0.37.01: It appears that the header doesn't always exist. For example, when an |
| 1836 | // Explorer window opens and is *initially* in icon or list mode vs. details/tiles mode, testing |
| 1837 | // shows that there is no header control. Testing also shows that there is exactly one column |
| 1838 | // in such cases but only for Explorer and other things that avoid creating the invisible columns. |
| 1839 | // For example, a script can create a ListView in Icon-mode and give it retrievable column data for |
| 1840 | // columns beyond the first. Thus, having the undetermined-col-count mode preserves flexibility |
| 1841 | // by allowing individual columns beyond the first to be retrieved. On a related note, testing shows |
| 1842 | // that attempts to explicitly retrieve columns (i.e. fields/subitems) other than the first in the |
| 1843 | // case of Explorer's Icon/List view modes behave the same as fetching the first column (i.e. Col3 |
| 1844 | // would retrieve the same text as specifying Col1 or not having the Col option at all). |
| 1845 | // Obsolete because not always true: Testing shows that a ListView always has a header control |
| 1846 | // (at least on XP), even if you can't see it (such as when the view is Icon/Tile or when -Hdr has |
| 1847 | // been specified in the options). |
| 1848 | HWND header_control; |
| 1849 | LRESULT col_count = -1; // Fix for v1.0.37.01: Use -1 to indicate "undetermined col count". |
| 1850 | if (SendMessageTimeout(aHwnd, LVM_GETHEADER, 0, 0, SMTO_ABORTIFHUNG, 2000, (PDWORD_PTR)&header_control) |
| 1851 | && header_control) // Relies on short-circuit boolean order. |
| 1852 | SendMessageTimeout(header_control, HDM_GETITEMCOUNT, 0, 0, SMTO_ABORTIFHUNG, 2000, (PDWORD_PTR)&col_count); |
| 1853 | // Return value is not checked because if it fails, col_count is left at its default of -1 set above. |
| 1854 | // In fact, if any of the above conditions made it impossible to determine col_count, col_count stays |
| 1855 | // at -1 to indicate "undetermined". |
| 1856 | |
| 1857 | // PARSE OPTIONS (a simple vs. strict method is used to reduce code size) |
| 1858 | bool get_count = tcscasestr(aOptions, _T("Count")); |
| 1859 | bool include_selected_only = tcscasestr(aOptions, _T("Selected")); // Explicit "ed" to reserve "Select" for possible future use. |
| 1860 | bool include_focused_only = tcscasestr(aOptions, _T("Focused")); // Same. |
| 1861 | LPTSTR col_option = tcscasestr(aOptions, _T("Col")); // Also used for mode "Count Col" |
| 1862 | int requested_col = col_option ? ATOI(col_option + 3) - 1 : -1; |
| 1863 | if (col_count > -1 && col_option && (requested_col < 0 || requested_col >= col_count)) // Specified column does not exist. |
| 1864 | _f_throw_value(ERR_PARAM1_INVALID, col_option); |
| 1865 | |
| 1866 | // IF THE "COUNT" OPTION IS PRESENT, FULLY HANDLE THAT AND RETURN |
| 1867 | if (get_count) |
| 1868 | { |
| 1869 | int result; // Must be signed to support writing a col count of -1 to aOutputVar. |
| 1870 | if (include_focused_only) // Listed first so that it takes precedence over include_selected_only. |
no test coverage detected