TL;博士
在 C++ MFC CListView 中,当 CListView 具有键盘焦点时,如何防止基于用户键入的字母进行自动选择?
情况:
MFC 应用程序使用 CListView 来显示包含字母数字字符串的行集合。如果我选择列表使其具有键盘焦点然后键入一个字母,则列表选择会跳转到第一列值以该字母开头的第一项。
即:如果我键入“r”,则列表列表选择会跳转到以字母“r”开头的第一个项目。如果我然后键入“b”,则列表选择会跳转到以字母 b 开头的第一个项目。等等。
当我使用 VS2019 新项目向导创建新应用程序时,此行为在 CListView 中是自动的。
问题一:
如何防止这种自动选择发生,同时不干扰向上/向下箭头键导航?
在对此进行打击的过程中,我发现带有 WC_LISTVIEW 类的直接 WIN32 窗口的行为也是如此,所以我认为必须有一种样式可以打开或关闭它?
如果它是一种样式,那么我可以在 OnInitialUpdate() 的 ModifyStyle() 调用中更改它,或者甚至只是使用它的 HWND 向控件发送消息?
所以......问题2:
我可以关闭它而不进入 CListView 的消息处理循环中的杂草吗?
评论
我不是在寻找 CListView 可以执行的高级多字母子字符串匹配搜索。
我希望 CListView 在我键入字母或数字时停止更改选择,并且我希望它继续更改选择以响应向上/向下箭头、向上翻页/向下翻页和主页/结束键的正常行为. 因此,如果您愿意,请关闭搜索。
代码
我可以发布更多代码,但这将是 VS2019 New Project -> C++ -> MFC-> Explorer Style 向导的输出。
我所做的唯一相关更改是将 CListView 派生类重命名为 MyCFileListView,并填充列表。
填充列表:
static void AddData(CListCtrl &ctrl, int row, int col, const wchar_t *str) {
LVITEM lv;
lv.iItem = row;
lv.iSubItem = col;
lv.pszText = (LPTSTR) str;
lv.mask = LVIF_TEXT;
if(col == 0)
ctrl.InsertItem(&lv);
else
ctrl.SetItem(&lv);
}
void MyCFileListView::OnInitialUpdate() {
CListView::OnInitialUpdate();
ModifyStyle(LVS_TYPEMASK, LVS_REPORT);
CListCtrl &the_list = GetListCtrl();
the_list.InsertColumn(0, L"File");
the_list.SetColumnWidth(0, 80);
the_list.InsertColumn(1, L"Size");
the_list.SetColumnWidth(1, 80);
the_list.InsertColumn(2, L"Modified");
the_list.SetColumnWidth(2, 80);
the_list.InsertColumn(3, L"Type");
the_list.SetColumnWidth(3, 80);
the_list.InsertColumn(4, L"Description");
the_list.SetColumnWidth(4, 80);
UINT ii = 0;
for (const FileInfo &fi: program_state.file_list) {
AddData(the_list, ii, 0, fi.filename.c_str());
AddData(the_list, ii, 1, fi.filesize.c_str());
AddData(the_list, ii, 2, L"NYI");
AddData(the_list, ii, 3, fi.filetype.c_str());
AddData(the_list, ii, 4, L"");
ii++;
}
}
其中 FileInfo 只是一个容器(应该是一个结构):
class FileInfo {
public:
FileInfo() : n_filesize(0), epoch_ms(0), is_dir(false) {};
virtual ~FileInfo() {
}
std::wstring filename;
std::wstring ext;
std::wstring fqfilename;
std::wstring filesize;
size_t n_filesize;
__int64 epoch_ms;
std::wstring mod_date;
std::wstring filetype;
std::wstring description;
std::wstring properties;
bool is_dir;
};
并且 program_state.file_list 是这样声明的:
class ProgramState {
public:
// ...
std::vector<FileInfo> file_list;
// ...
};
我已经浏览了 MS 在 CListViews、WIN32 ListViews AKA WC_LISTVIEW、它们的样式和扩展样式上的页面,但找不到关于此行为的任何内容:
https://docs.microsoft.com/en-us/cpp/mfc/reference/clistview-class?view=msvc-160
https://docs.microsoft.com/en-us/windows/win32/controls/list-view-controls-overview
https://docs.microsoft.com/en-us/windows/win32/controls/extended-list-view-styles
https://docs.microsoft.com/en-us/windows/win32/msi/listview-control
...以及其他太多,无法列出。
就好像这种行为非常好,以至于没有人愿意禁用它:-)