C++ MFC 键盘加速器
Posted
技术标签:
【中文标题】C++ MFC 键盘加速器【英文标题】:C++ MFC Keyboard Accelerators 【发布时间】:2014-02-10 21:52:20 【问题描述】:我有一个CWinAppEx
派生类和一个CFrameWndEx
派生类,但我终生无法理解如何使用键盘加速器。
我有一个带加速器的加速器表:
ID: ID_CLOSE_FOCUSED_WINDOW
Modifier: Ctrl
Key: W
Type: VIRTKEY
我的CFrameWndEx
派生类的消息映射中有这一行:
ON_COMMAND(ID_CLOSE_FOCUSED_WINDOW, CloseLastFocusedWindow)
我尝试在CFrameWndEx
派生类和PreTranslateMessage
调用TranslateAccelerators
中覆盖PreTranslateMessage
,但我仍然没有收到与加速器表中的ID 相同的命令 - 没有点击CloseLastFocusedWindow
函数中的断点。
有人能解释一下吗?我觉得我正确地遵循了文档,但它对我不起作用。
提前致谢
【问题讨论】:
我认为加速器的资源 ID(例如:IDR_MAINFRAME
)应该与用于加载帧的资源 ID 匹配
感谢 Edward,我的资源 ID 与用于加载框架的 ID 匹配。
【参考方案1】:
几个想法。您确定 CloseLastFocusedWindow 的签名正确吗?
应该相当于:
afx_msg void CloseLastFocusedWindow();
另外,DECLARE_MESSAGE_MAP() 是否出现在上述声明之前?
我认为 CFrameWndEx 默认会为您调用 TranslateAccelerator。一般来说,您只需要关注 LoadAccelerators 和 TranslateAccelerator 在不自动处理它们的地方(例如对话窗口等)。
编辑
还要注意框架构造的方式很重要。例如,如果您通过 CSingleDocTemplate 构造一个框架窗口,那么传递给 CSingleDocTemplate 构造函数的第一个参数将控制加载哪个加速器表。
例子:
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CMyView));
在上面的代码中,将加载 IDR_MAINFRAME 加速器表,并且应在此处输入任何所需的加速器。
【讨论】:
嗨,马克,感谢您的回复。 CloseLastFocusedWindow 具有确切的签名,包括 afx_msg。并且消息映射也正确形成 - 我正在使用它来捕获许多其他命令消息。我想知道它是否会为我调用 TranslateAccelerator,因为它肯定会调用 LoadAccelerators(如果我自己调用 LoadAccelerators 则断言,因为它不止一次调用该函数)。 你是如何创建框架窗口的? 我更新了我的答案以讨论框架窗口构造注意事项。让我知道这是否有帮助。 好点,但不幸的是,IDR_MAINFRAME 是资源 ID,我有 LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL);加载 CFrameWndEx 类。【参考方案2】:我现在遇到了类似的问题:除了默认视图(在 CSingleDocTemplate 中指定的那个)之外,我还以非标准方式创建了另一个视图。在处理了关闭非标准视图的 Ctrl+W 组合后,主菜单停止工作。后来发现我忘记设置一个新的活动视图。这样做的副作用是,文档没有收到任何命令,例如从提到的主菜单中。
所以我的建议是:当您关闭(非标准创建的)视图时,不要忘记致电 CFrameWnd::SetActiveView
。
【讨论】:
以上是关于C++ MFC 键盘加速器的主要内容,如果未能解决你的问题,请参考以下文章
带有 Visual Studio 2010 的 MFC-SDI 应用程序:新的键盘快捷键不起作用