MFC 自定义 Tab 键事件处理程序
MFC custom tab key event handler
问题:
有没有办法在 MFC CEdit 中捕获 <Tab>
字符/事件,以便我可以覆盖默认的 Tab 键顺序行为?换句话说:有没有办法以编程方式注册和取消注册 <Tab>
处理程序?
上下文:
我知道 MFC 的 Tab 键排序机制,您可以在编译时指定一个顺序,以 Tab 键浏览可见控件。我想要做的是 CEdit 的子类,以便在此 CEdit 中按 <Tab>
通过预设的字符串列表循环相邻标签(只读 CEdit),一旦列表完成,按 <Tab>
再次将焦点移出并让 MFC 的默认选项卡排序再次接管。
我的直觉告诉我这应该是可能的,但我找不到任何有用的文档。如果 MFC 有办法动态注册和取消注册 <Tab>
事件(或任意键事件),那么这将非常简单,但我还没有找到它。
总结
基本上,假设我有 4 个编辑框 e1、e2、e3、e4;和 3 个字符串的列表; str1、str2、str3 进入对话框中其他地方的标签。如果我们从 e1 中的光标开始,我希望 Tab 键顺序如下:
- e1
- e2
- e3
- e3, str1
- e3, str2
- e3, str3
- e4
这可能吗?是否有其他方式获得相同的行为?
假设您有 4 个编辑控件 e1、e2、e3、e4。您希望他们按以下顺序跳转:3,2,4,1
覆盖 OnInitDialog() 并像这样移动它们:
e3.SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
e2.SetWindowPos(&e3, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
e4.SetWindowPos(&e2, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
e1.SetWindowPos(&e4, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
如果您以相反的 Tab 键顺序移动它们,它也有效:
e1.SetWindowPos(0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
e4.SetWindowPos(0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
e2.SetWindowPos(0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
e3.SetWindowPos(0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
如果以后必须 move/resize 控件,请添加 SWP_NOZORDER
标志以防止更改 Tab 键顺序。
可能还有其他 'elegant' 方法可以做到这一点,但是,如果我理解您的描述,我认为这会奏效。您可以像这样使用 PreTranslateMessage 来完成您想要的。
BOOL CMFCApplication6Dlg::PreTranslateMessage(MSG* pMsg)
{
static int i = 0;
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB)
{
CWnd* pFocusControl = GetFocus();
if (pFocusControl->GetDlgCtrlID() == IDC_EDIT3)
{
if (i < 3)
{
CString msg;
msg.Format("Test %d", i++);
GetDlgItem(IDC_EDIT4)->SetWindowText(msg);
return TRUE;
}
}
}
return CDialog::PreTranslateMessage(pMsg);
}
在上面的示例代码中,我使用了 5 个水平放置在对话框中的编辑框。该选项卡从左侧的第一个编辑开始,然后将选项卡直到它到达禁用编辑框之前的编辑控件。再次点击选项卡将在禁用的编辑框中显示 3 条文本消息(一次一条)。第三条消息后,下一个标签会移动到右边第五个编辑框。
问题:
有没有办法在 MFC CEdit 中捕获 <Tab>
字符/事件,以便我可以覆盖默认的 Tab 键顺序行为?换句话说:有没有办法以编程方式注册和取消注册 <Tab>
处理程序?
上下文:
我知道 MFC 的 Tab 键排序机制,您可以在编译时指定一个顺序,以 Tab 键浏览可见控件。我想要做的是 CEdit 的子类,以便在此 CEdit 中按 <Tab>
通过预设的字符串列表循环相邻标签(只读 CEdit),一旦列表完成,按 <Tab>
再次将焦点移出并让 MFC 的默认选项卡排序再次接管。
我的直觉告诉我这应该是可能的,但我找不到任何有用的文档。如果 MFC 有办法动态注册和取消注册 <Tab>
事件(或任意键事件),那么这将非常简单,但我还没有找到它。
总结
基本上,假设我有 4 个编辑框 e1、e2、e3、e4;和 3 个字符串的列表; str1、str2、str3 进入对话框中其他地方的标签。如果我们从 e1 中的光标开始,我希望 Tab 键顺序如下:
- e1
- e2
- e3
- e3, str1
- e3, str2
- e3, str3
- e4
这可能吗?是否有其他方式获得相同的行为?
假设您有 4 个编辑控件 e1、e2、e3、e4。您希望他们按以下顺序跳转:3,2,4,1
覆盖 OnInitDialog() 并像这样移动它们:
e3.SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
e2.SetWindowPos(&e3, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
e4.SetWindowPos(&e2, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
e1.SetWindowPos(&e4, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
如果您以相反的 Tab 键顺序移动它们,它也有效:
e1.SetWindowPos(0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
e4.SetWindowPos(0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
e2.SetWindowPos(0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
e3.SetWindowPos(0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
如果以后必须 move/resize 控件,请添加 SWP_NOZORDER
标志以防止更改 Tab 键顺序。
可能还有其他 'elegant' 方法可以做到这一点,但是,如果我理解您的描述,我认为这会奏效。您可以像这样使用 PreTranslateMessage 来完成您想要的。
BOOL CMFCApplication6Dlg::PreTranslateMessage(MSG* pMsg)
{
static int i = 0;
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB)
{
CWnd* pFocusControl = GetFocus();
if (pFocusControl->GetDlgCtrlID() == IDC_EDIT3)
{
if (i < 3)
{
CString msg;
msg.Format("Test %d", i++);
GetDlgItem(IDC_EDIT4)->SetWindowText(msg);
return TRUE;
}
}
}
return CDialog::PreTranslateMessage(pMsg);
}
在上面的示例代码中,我使用了 5 个水平放置在对话框中的编辑框。该选项卡从左侧的第一个编辑开始,然后将选项卡直到它到达禁用编辑框之前的编辑控件。再次点击选项卡将在禁用的编辑框中显示 3 条文本消息(一次一条)。第三条消息后,下一个标签会移动到右边第五个编辑框。