【MFC】光标自动聚焦输入框,测试完成后 清空输入框并重新聚焦输入框。为什么初始化时光标可自动聚集输入框,而测试结束后聚焦输入框失败呢??

光标自动聚焦输入框,扫码后,点击Test按键测试完成后, 清空输入框并重新聚焦输入框,等待下次扫码测试;

为什么初始化时光标可自动聚集输入框,而测试结束后聚焦输入框失败呢?

1.初版实现

1.1 添加控件

输入编辑框ID为:IDC_EDIT_BARCODE
添加变量:CEdit m_editBarcode;
Test按键ID为:IDC_BUTTON_START
在这里插入图片描述

1.2 头文件

private:
	CEdit m_editBarcode;	
	CString CstrBarcode;
	std::string SN;

protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持
	virtual BOOL PreTranslateMessage(MSG* pMsg);  // 处理扫码枪输入

1.3.cpp实现

BOOL CDtSampleDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
///
///初始化其他内容

///
    m_editBarcode.SetFocus();  // 初始聚焦到条码框

	return FALSE;  // 必须返回FALSE,确保焦点设置生效
}

条码框处理

#pragma region"条码框处理"
BOOL CDtSampleDlg::PreTranslateMessage(MSG* pMsg) {
	if (pMsg->message == WM_KEYDOWN) {
		if (pMsg->wParam == VK_RETURN) {  // 扫码枪以回车结束输入
			GetDlgItemText(IDC_EDIT_BARCODE, CstrBarcode);

			//--- 可选:校验条码格式(示例:长度至少6位) ---
			if (CstrBarcode.GetLength() < 6) {
				MessageBox(_T("无效条码!"), _T("错误"), MB_ICONERROR);
				SetDlgItemText(IDC_EDIT_BARCODE, _T(""));
				m_editBarcode.SetFocus();
				return TRUE;  // 拦截消息
			}
			//--- 校验结束 ---

			//条码框字符转换为 string类型,赋值给SN
			//SN = Cstr2str(CstrBarcode);  
			SN = CstrBarcode.GetString();

			return TRUE;  // 拦截回车消息
		}
	}
	return CDialogEx::PreTranslateMessage(pMsg);
}
#pragma endregion

按键触发测试功能


void CDtSampleDlg::TestFlow()
{

	///
	///其他内容
	
	///

	if (!test1())
	{
		msg(this, "test1测试 失败!\r\n");
		return;
	}
	msg(this, "关test1测试 成功!\r\n");

	if (!test2())
	{
		msg(this, "test2测试 失败!\r\n");
		return;
	}
	msg(this, "关test2测试 成功!\r\n");


	// 清空输入框并重新聚焦
	SetDlgItemText(IDC_EDIT_BARCODE, _T(""));
	m_editBarcode.SetFocus();
}
void CDtSampleDlg::OnBnClickedButtonTest()
{
	TestFlow()}

1.4 测试效果

运行后
在这里插入图片描述

扫码,然后点击 Test 按钮测试
在这里插入图片描述

测试完毕后,清空条码框,但是聚焦输入框失败
在这里插入图片描述

2 问题分析

问题原因分析

在MFC中,‌焦点设置失败‌通常由以下原因导致:

‌1.模态窗口干扰‌
TestFlow() 中频繁调用 msg() 显示消息,若其内部使用 AfxMessageBoxMessageBox,会创建模态对话框,导致主窗口失去焦点。关闭模态窗口后,焦点可能未正确返回到原控件。

‌2. UI线程阻塞‌
测试流程中的耗时操作(如 Sleep(1500)、硬件控制)会阻塞UI线程,导致 SetFocus() 调用未及时处理。

3.控件状态变更‌
测试过程中可能禁用或隐藏了条码框(IDC_EDIT_BARCODE),导致 SetFocus() 失效。

4‌.默认按钮抢占焦点‌
如果对话框定义了默认按钮(如“Test”按钮),按下回车时会触发按钮点击,测试结束后焦点会停留在按钮上。

3 解决方案代码

3.1 步骤1:异步设置焦点 ( 完美解决)

通过 PostMessage 延迟焦点设置,确保在UI消息队列空闲时执行。

头文件

// 在对话框类头文件中添加自定义消息
#define WM_SETFOCUS_BARCODE (WM_USER + 102)

protected:
	// 设置焦点到条码框
	afx_msg LRESULT OnSetFocusBarcode(WPARAM, LPARAM);


// 消息映射声明
BEGIN_MESSAGE_MAP(CDtSampleDlg, CDialogEx)
    ON_MESSAGE(WM_SETFOCUS_BARCODE, &CDtSampleDlg::OnSetFocusBarcode)
END_MESSAGE_MAP()

// 消息处理函数
LRESULT CDtSampleDlg::OnSetFocusBarcode(WPARAM, LPARAM) {
    m_editBarcode.SetFocus(); // 设置焦点到条码框
    return 0;
}

// 修改TestFlow末尾代码
void CDtSampleDlg::TestFlow() {
    // ...原有代码...

    // 清空条码框并异步设置焦点
    SetDlgItemText(IDC_EDIT_BARCODE, _T(""));
    PostMessage(WM_SETFOCUS_BARCODE); 
}

问题解决,测试完成后,清空输入框并重新自动聚焦输入框。

在这里插入图片描述

3.2 如果还不行,追加一下方法

步骤2:禁用默认按钮行为
在对话框初始化时移除默认按钮的 BS_DEFPUSHBUTTON 样式,防止其抢占焦点。

BOOL CDtSampleDlg::OnInitDialog() {
    CDialogEx::OnInitDialog();

    // 移除"开始测试"按钮的默认按钮属性
    CButton* pStartButton = (CButton*)GetDlgItem(IDC_BUTTON_START);
    if (pStartButton) {
        pStartButton->ModifyStyle(BS_DEFPUSHBUTTON, BS_PUSHBUTTON);
    }

    // 初始聚焦条码框
    m_editBarcode.SetFocus();
    return FALSE; // 必须返回FALSE以阻止MFC自动设置焦点
}

步骤3:验证控件状态
确保测试过程中未禁用或隐藏条码框。

void CDtSampleDlg::TestFlow() {
    // 确保条码框处于可聚焦状态
    GetDlgItem(IDC_EDIT_BARCODE)->EnableWindow(TRUE);
    GetDlgItem(IDC_EDIT_BARCODE)->ShowWindow(SW_SHOW);

    // ...原有代码...
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

R-G-B

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值