简体   繁体   English

在C ++ MFC应用程序中的应用程序内部模拟键盘输入

[英]Simulate keyboard input inside app in C++ MFC app

I created a dialog MainDialog.cpp with 2 edit controls whose IDs are IDC_EDITCONTROL_A and IDC_EDITCONTROL_B , and have variables defined as m_editControlA and m_editControlB , respectively. 我创建了一个对话框MainDialog.cpp其中包含2个 ID为IDC_EDITCONTROL_AIDC_EDITCONTROL_B 编辑控件 ,并且分别将变量定义为m_editControlAm_editControlB

Also, I have 2 buttons whose IDs are IDC_MFCBUTTON_KEY_X and IDC_MFCBUTTON_KEY_Y , and variables are m_buttonKeyX and m_buttonKeyY , respectively. 此外,我有2个按钮,其ID为IDC_MFCBUTTON_KEY_XIDC_MFCBUTTON_KEY_Y ,变量分别为m_buttonKeyXm_buttonKeyY

Below is the code in the source file 下面是源文件中的代码

#include "afxdialogex.h" 

IMPLEMENT_DYNAMIC(CMainDialog, CDialogEx)

CMainDialog::CMainDialog(CWnd* pParent): CDialogEx(IDD_MAIN_DIALOG, pParent)
{
}

CMainDialog::~CMainDialog()
{
}

void CMainDialog::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);

    DDX_Control(pDX, IDC_EDITCONTROL_A, m_editControlA);
    DDX_Control(pDX, IDC_EDITCONTROL_B, m_editControlB);
    DDX(Control(pDX, IDC_MFCBUTTON_KEY_X, m_buttonKeyX);
    DDX(Control(pDX, IDC_MFCBUTTON_KEY_Y, m_buttonKeyY);
}

BEGIN_MESSAGE_MAP(CMainDialog, CDialogEx)
    ON_EN_CHANGE(IDC_EDITCONTROL, &CMainDialog::OnEnChangeEditA)
    ON_BN_CLICKED(IDC_MFCBUTTON_KEY_X, &CMainDialog::OnBnClickedButtonX)
    ON_BN_CLICKED(IDC_MFCBUTTON_KEY_Y, &CMainDialog::OnBnClickedButtonY)
END_MESSAGE_MAP()

void CMainDialog::OnBnClickedButtonX()
{
    m_editControlA.SetWindowTextW(_T("X"));  // test
}

void CMainDialog::OnBnClickedButtonX()
{
    m_editControlA.SetWindowTextW(_T("Y"));  // test
}

I am trying to understand how I can have each button send their respective character (ie X or Y in this example) to the selected edit control if one is selected . 我试图了解如何让每个按钮各自的字符(在本示例中为XY )发送给选定的编辑控件( 如果选择了一个) Essentially, I would like to simulate keyboard input . 本质上,我想模拟键盘输入

I have read the docs about how to simulate keyboard events and also the sendMessage but I could not understand how to implement it since my C++ knowledge is very basic. 我已经阅读了有关如何模拟键盘事件以及sendMessage的文档,但是由于我的C ++知识非常基础,所以我无法理解如何实现它。 Also, following my previous question I have found that the GetFocus would be useful but still my main issue currently is sending the input. 另外,在我之前的问题之后,我发现GetFocus很有用,但目前我的主要问题仍然是发送输入。

Any example code or useful link could be very useful for me to learn how I can simulate a keyboard input inside an app. 任何示例代码或有用的链接对于我学习如何在应用程序内部模拟键盘输入都可能非常有用。

The characters are sent from the OS to the edit controls using the WM_CHAR message. 使用WM_CHAR消息将字符从操作系统发送到编辑控件。

In reality it is a bit more complex than that, but you do not need to emulate the entire WM_KEYUP WM_KEYDOWN message sequence, since its end result is to generate a WM_CHAR message. 实际上,它比这复杂一些,但是您不需要模拟整个WM_KEYUP WM_KEYDOWN消息序列,因为它的最终结果是生成WM_CHAR消息。

You can use CWnd::PostMessage to send characters directly to your edit controls, even when they do not have the focus. 您可以使用CWnd :: PostMessage将字符直接发送到您的编辑控件,即使它们没有焦点。

You have probably already found the documentation for WM_CHAR here: https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms646276(v=vs.85).aspx 您可能已经在这里找到WM_CHAR的文档: https ://msdn.microsoft.com/fr-fr/library/windows/desktop/ms646276( v= vs.85).aspx

oops.. excuse my french, ths english doc is here https://msdn.microsoft.com/en-us/library/windows/desktop/ms646276(v=vs.85).aspx 哎呀..请问我的法语,英语文档在这里https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms646276(v=vs.85).aspx

(just changing the fr-fr to en-us does the trick, it probably works for all other languages, neat! (只需将fr-fr更改为en-us即可达到目的,它可能适用于所有其他语言,整洁!

  • wParam holds the character you want to send. wParam保存您要发送的字符。 Either an plain ASCII character, or one of the VK_ constants... I suggest you use the unicode version WM_CHARW, as most windows software uses unicode nowadays. 可以是普通的ASCII字符,也可以是VK_常量之一...我建议您使用Unicode版本WM_CHARW,因为当今大多数Windows软件都使用Unicode。 The notation for wide chars is either L'X' or _T('X'), the unicode (UTF-16) character type is wchar_t. 宽字符的表示法为L'X'或_T('X'),Unicode(UTF-16)字符类型为wchar_t。

  • lParam contains other keystroke details, 0 should be fine for what you want to do. lParam包含其他击键详细信息,0应该适合您要执行的操作。

to send X, simply call 发送X,只需致电

 m_editControlA.PostMessage(WM_CHAR, _T('X'));  

When using the _T() notation, the character (or string) literal between the parenthesis will be automatically converted to the right character width for your app's unicode setting (you should set that to UNICODE, since that's what the OS is using, and is also the only valid encoding for Windows CE, for example, and you should get used to manipulating this type. 使用_T()表示法时,括号之间的字符(或字符串)文字将自动转换为应用程序unicode设置的正确字符宽度(您应将其设置为UNICODE,因为这是操作系统使用的,并且是也是Windows CE的唯一有效编码,例如,您应该习惯于操纵这种类型。

the _T() macros and _t* overrides for almost all C library functions operating on strings are defined in tchar.h, which is included by Visual Studio in stdafx.h. tchar.h中定义了几乎所有对字符串进行操作的C库函数的_T()宏和_t *替代,tchar.h中定义了该功能,Visual Studio在stdafx.h中包含了该功能。 Under MFC, you'll mostly use CString, but it's good to know where these things are. 在MFC下,您将主要使用CString,但是最好知道这些东西在哪里。

[EDIT] When you get that running, you should start playing with WM_KEYDOWN. [EDIT]开始运行时,您应该开始使用WM_KEYDOWN进行游戏。 You will discover that PostMessage(WM_CHAR, VK_ESCAPE) directly to your dialog does not close it, while a PostMessage(WM_KEYDOWN, VK_ESCAPE) does. 您会发现直接发送到对话框的PostMessage(WM_CHAR,VK_ESCAPE)不会关闭它,而PostMessage(WM_KEYDOWN,VK_ESCAPE)会关闭它。 And that m_editBox.PostMessage(WM_KEYDOWN, _T('X')) will send a lower key 'x' to your edit box. 并且该m_editBox.PostMessage(WM_KEYDOWN,_T('X'))将向您的编辑框发送一个较低的键'x'。 But that's another topic to ivestigate. 但这是另一个引起争议的话题。

Have fun with MFC! 玩MFC!

For your last question: 对于您的最后一个问题:

Sure, but it gets a bit more complicated, as your button will gain focus, as soon as you click on it. 当然可以,但是会变得更加复杂,因为单击按钮后您的按钮将获得焦点。 You'd have to create handlers for EN_SETFOCUS for eeach of your edit boxes, and add a CWnd* data member to keep track of the last edit box that had focus. 您必须为每个编辑框创建EN_SETFOCUS的处理程序,并添加CWnd *数据成员以跟踪上一个具有焦点的编辑框。

Your EN_SETFOCUS handlers should look something like this 您的EN_SETFOCUS处理程序应如下所示

void CdlgDlg::OnEnSetfocusEdit1()
{ 
    m_pWndLastFocus = &m_edit1;
}

Don't forget to set the pointer to NULL in your constructor and to chjeck it's valid before calling m_pWndLastFocus->PostMessage() though. 但是,不要忘记在构造函数中将指针设置为NULL,并在调用m_pWndLastFocus->PostMessage()之前使其有效。

在MFC中合成输入的方法是使用SendInput方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM