屏幕键盘上的 MFC C++ 作为父对话框

Posted

技术标签:

【中文标题】屏幕键盘上的 MFC C++ 作为父对话框【英文标题】:MFC C++ on screen keyboard as parent dialog 【发布时间】:2016-04-17 20:30:05 【问题描述】:

我想扩展第三方应用程序的功能,该应用程序使用键盘快捷键在触摸屏显示器上使用。 我的计划是制作一个屏幕键盘,将击键(虚拟)提供给应用程序,并更改窗口样式以将其嵌入到键盘中。

由于应用程序(Mach3) 支持使用插件扩展功能,这就是我想要实现目标的方式。

对于嵌入,我修改了 here 的代码,以便在加载 mach3 时,应用程序对话框立即嵌入到我的对话框中。

对于键盘功能,我使用来自here 的代码为窗口提供WS_EX_NOACTIVATE 样式并正确移动句柄。

我遇到的问题是,当我将焦点放在另一个窗口(例如记事本)并按下按钮以生成按键时,其他应用程序会正确接收按键,但是当我将焦点放在嵌入式窗口并按下一个按钮,焦点转移到按钮上,子对话框没有收到任何按键。

如何防止焦点像这样改变? 这是我缺少的一件简单的事情,还是我需要彻底改变我的方法?

我会发布一些代码,但其中有很多,我不确定哪些代码与解决此问题最相关。

【问题讨论】:

***.com/questions/1372202/… 这似乎有所不同,我不希望我的对话框吞下按键,我希望它们被传递到应用程序窗口并且这样做时焦点不会改变,我想重点是这里的大问题。 我认为您的问题是,由于嵌入式应用程序位于还包含虚拟键盘的对话框内,因此将焦点转移回前一个窗口(在 OnMouseMove 中)的代码可能只是将焦点转移到您自己的对话框和虚拟键盘按钮。我觉得这需要一些测试来确定。对了,我在MFC那篇文章的cmets部分看到,对项目有个更正,你试过了吗? 我错过了,谢谢,我在工作时无法访问 VS2013(我用来编译它的东西),所以当我得到时我会试试这个家。 我已经做出了 cmets 中显示的更改,并且没有激活部分效果更好(窗口似乎根本无法保持焦点但仍然可以移动)但是我仍然无法保持焦点当我按下按钮时,在嵌入式对话框上。事实上,只要我将鼠标移出嵌入对话框的区域,具有焦点的控件(MDI 行)就会失去焦点 【参考方案1】:

我找到了问题的原因,现在我可以创建一个嵌入式对话框,并将父对话框用作屏幕键盘。

首先,如上所述,我需要对我的键盘代码进行一些更改,特别是文章所说的被覆盖的OnNcLButtonDown

void COnScreenKeyboardDlg::OnNcLButtonDown(UINT nHitTest, CPoint point)

 if (!m_hForegroundWnd)
 
  // store current foreground window
  m_hForegroundWnd = ::GetForegroundWindow();
  // temporarily make this dialog an activatable window
  ModifyStyleEx(WS_EX_NOACTIVATE,0);
  // make this dialog foreground
  SetForegroundWindow();
 
 CDialog::OnNcLButtonDown(nHitTest, point);

但实际上应该是:

void CWrapperDialog::OnNcLButtonDown(UINT nHitTest, CPoint point) 
    SetForegroundWindow();
    CDialog::OnNcLButtonDown(nHitTest, point);

其次,文章说用:覆盖OnMouseMove

void COnScreenKeyboardDlg::OnMouseMove(UINT nFlags, CPoint point)

 if (m_hForegroundWnd)
 
  // make the previous foreground window active
  ::SetForegroundWindow(m_hForegroundWnd);
  // make this dialog non-activating
  ModifyStyleEx(0,WS_EX_NOACTIVATE);
  // set it to NULL to mark that we do not need to do this again
  m_hForegroundWnd = NULL;
 
 CDialog::OnMouseMove(nFlags, point);

下面的评论将其“更正”为:

void CWrapperDialog::OnMouseMove(UINT nFlags, CPoint point) 
    ::SetActiveWindow(0);
    CDialog::OnMouseMove(nFlags, point);

但是我发现使用这段代码时,每当我移动鼠标时,我都会因为焦点变化而闪烁,所以我完全省略了它。

最后,键盘示例使用DoModal 创建对话框,而我使用的是Create

我创建了一个可以用AfxBeginThread 调用的包装函数:

UINT CWrapperDialog::ThreadDoModal(LPVOID pParam)
    CWrapperDialog* dlg;
    dlg = ((CWrapperDialog*)pParam);
    dlg->DoModal();
    return 0;

并称它为:

dlg = new CWrapperDialog;
AfxBeginThread(dlg->ThreadDoModal, dlg);

现在消息正在正确传递。

感谢 o_weisman 提供有关示例更改的提示,因为这产生了巨大的差异。

【讨论】:

以上是关于屏幕键盘上的 MFC C++ 作为父对话框的主要内容,如果未能解决你的问题,请参考以下文章

华为机试真题 C++ 实现5键键盘

Android 键盘 长按关机显示对话框时,按键盘任意键屏幕顶部状态栏会显示出来其他阴影

钩子编程(HOOK) 安装进程内键盘钩子

键盘u变成4了怎么办

如果显示键盘,iOS HTML 复选框屏幕将被阻止

有没有win10上用的,能把键盘上某些按键映射到屏幕上的软件