none
实现一个软键盘,使得软键盘也能中文输入 RRS feed

  • 问题

  • 各位大佬,我想问问为什么软键盘的中文输入是怎么实现的,我就做了两个按钮进行试验,发现不能连打文字,比如说正常情况下输入“wm”,会显示“我们”,但是现在不能给提示了,需要做什么特别的处理吗?新人表示一脸懵逼,求教


    void CtestDlg::OnBnClickedButton1()

    {
    	// TODO: 在此添加控件通知处理程序代码
    
    	CEdit* pBtn = (CEdit*)GetDlgItem(IDC_EDIT1);//必须进行强制类型转换
    	HWND hBtn = pBtn->GetSafeHwnd();
    	::SetFocus(hBtn);
    	keybd_event(88, 0, 0, 0);
    	keybd_event(88, 0, KEYEVENTF_KEYUP, 0);
    }
    
    
    void CtestDlg::OnBnClickedButton2()
    {
    	// TODO: 在此添加控件通知处理程序代码
    
    	CEdit* pBtn = (CEdit*)GetDlgItem(IDC_EDIT1);//必须进行强制类型转换
    	HWND hBtn = pBtn->GetSafeHwnd();
    	::SetFocus(hBtn);
    	keybd_event(85, 0, 0, 0);
    	keybd_event(85, 0, KEYEVENTF_KEYUP, 0);
    }


    2019年8月19日 7:16

答案

  • 你好,

    如果这个问题已经解决,请将你认为有价值的回复标记为答案,这会帮助其他有相同问题的社区成员更快地找到解决方案,谢谢。

    Best Regards,

    Suarez Zhou

    2019年8月22日 5:33

全部回复

  • 图的画上传不了。。

    界面就是一个文本框、字母X按钮、字母U按钮

    2019年8月19日 7:18
  • 你好,

    >>图的画上传不了。。

    这是由于你的账号还未验证。请到下方的链接里留言,会有相关工作人员为你的账号提供验证。

    https://social.technet.microsoft.com/Forums/en-US/dc4002e4-e3de-4b1e-9a97-3702387886cc/verify-account-42?forum=reportabug

    Best Regards,

    Suarez Zhou

    2019年8月19日 8:05
  • 您好,能直接看看代码吗
    2019年8月19日 8:12
  • 你好,

    经过测试,我认为是这其中存在着很复杂的消息错误。我们来梳理一下,你的按键消息是放在OnBnClickedButton函数里的,这函数响应按键的点击消息,点击意味着鼠标左键需要按下抬起这两个动作,所以当按键抬起时触发按键的点击消息,又同时触发了鼠标左键的抬起消息,我并不清楚这其中的顺序关系,但结果是这样的操作造成了程序错误。

    如果你需要实现虚拟键盘消息,不如尝试再鼠标左键按下的消息里去做,通过按键的控件ID号去获取控件的RECT范围,并跟point比较,以确定鼠标点击是否是按键上,如果是则执行发送键盘消息。测试发现符合你的要求。

    void CMFCApplication77Dlg::OnLButtonDown(UINT nFlags, CPoint point)
    {
    	// TODO: Add your message handler code here and/or call default
    	
    	CEdit* pBtn = (CEdit*)GetDlgItem(IDC_EDIT1);//必须进行强制类型转换
    	HWND hBtn = pBtn->GetSafeHwnd();
    	::SetFocus(hBtn);
    	::keybd_event(85, 0, 0, 0);
    	::keybd_event(85, 0, KEYEVENTF_KEYUP, 0);
    
    	CDialogEx::OnLButtonDown(nFlags, point);
    }

    Best Regards,

    Suarez Zhou


    2019年8月19日 9:13
  • 你好,

    你的问题得到解决了吗?如果解决了,请标记有帮助的回复为正确答案,或者你有更好的解决方案,我们也欢迎你能分享出来并标记为答案,这会帮助其他有相同问题的社区成员更快地找到答案。如果你的问题还没有得到解决,我们欢迎你随时过来提问。

    Best Regards,

    Suarez Zhou

    2019年8月21日 1:09
  • 您好,有没有详细点的代码啊,刚开始学不明白
    2019年8月21日 6:09
  • 您好,代码我就写了我发出来的那部分,其他都是系统生成的
    2019年8月21日 6:33
  • 还没解决。。。。
    2019年8月21日 6:54
  • 你好,

    很抱歉,我在测试你所说的问题是否还有另外一种解决方案,所以没有能及时回复你的消息。

    首先使用按钮来做这件事似乎是不可能的,按钮也是个CWnd类,算是一种另类的窗口,当你点击它,会使得窗口焦点发生改变,尽管你在按钮的点击事件中加入让窗口焦点集中在编辑框的代码,但有那么一瞬间窗口焦点依旧是会改变的,所以输入法的内容会被清空。

    在仔细观察了OSK键盘和Tabtip键盘,我发现它们可能也不是拿的按钮来做按键。它们很有可能用三张图片来做出按钮一样的效果。例如底下图片中这样,分别为鼠标不放在上面,鼠标放在上面,鼠标点击三种情况的图片,来做出点击它跟点击按钮一样的动态效果。

                     

    回到你的问题,我更推荐你用图片代替按钮来做。下面我将展示程序中关键的代码及程序的实际运行结果。

    //视图类头文件需要添加图片资源和编辑框控件
    class CMFCApplication84View : public CView
    {
    public:
            CEdit *edit;
    	int count = 0;
    	BITMAP bm;
    
    }
    //视图类.cpp文件
    //鼠标移动的消息函数去判断鼠标是否在图片上
    void CMFCApplication84View::OnMouseMove(UINT nFlags, CPoint point)
    {
    	// TODO: Add your message handler code here and/or call default
    	if (point.x < (300 + bm.bmWidth) && point.x > 300 && point.y > 0 && point.y < (0 + bm.bmHeight))
    	{
    		count = 1;
    		OnPaint();
    	}
    	else
    	{
    		count = 0;
    		OnPaint();
    	}
    	CView::OnMouseMove(nFlags, point);
    }
    
    //WM_PAINT消息里是绘制图片,根据计数的count来控制画什么图
    void CMFCApplication84View::OnPaint()
    {
    	//CPaintDC dc(this); // device context for painting
    					   // TODO: Add your message handler code here
    					   // Do not call CView::OnPaint() for painting messages
    	CClientDC dc(this);
    	CBitmap Bitmap;
    	CDC MemDC;
    	if (count == 0)
    		Bitmap.LoadBitmap(IDB_BITMAP3);//将图片资源变为白底的1
    	else if (count == 1)
    		Bitmap.LoadBitmap(IDB_BITMAP2);//将图片资源变为灰底的1
    	else if (count == 2)
    		Bitmap.LoadBitmap(IDB_BITMAP1);//将图片资源变为蓝底的1
    	Bitmap.GetObject(sizeof(BITMAP), &bm);
    	MemDC.CreateCompatibleDC(&dc);
    	CBitmap *pOldBitmap = MemDC.SelectObject(&Bitmap);
    	dc.BitBlt(300, 0, bm.bmWidth, bm.bmHeight, &MemDC, 0, 0, SRCCOPY);
    	MemDC.SelectObject(pOldBitmap);
    }
    
    //WM_CREATE消息里完成控件和图片资源的初始化
    int CMFCApplication84View::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    	if (CView::OnCreate(lpCreateStruct) == -1)
    		return -1;
    	CBitmap Bitmap;
    	Bitmap.LoadBitmap(IDB_BITMAP3);
    	Bitmap.GetObject(sizeof(BITMAP), &bm);
    	edit = new CEdit;
    	edit->Create(WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(300, 400, 600, 600), this, 10011);
    	edit->ShowWindow(SW_SHOW);
    	return 0;
    }
    
    //鼠标左键抬起消息里判断鼠标是否按在了图片上,可能用鼠标左键按下消息更好,
    //因为有时候鼠标按下,然后移动出图片范围再抬起会导致程序运行不按设计的要求来。
    void CMFCApplication84View::OnLButtonUp(UINT nFlags, CPoint point)
    {
    	// TODO: Add your message handler code here and/or call default
    	if (point.x < (300 + bm.bmWidth) && point.x > 300 && point.y > 0 && point.y < (0 + bm.bmHeight))
    	{
    		count = 2;
    		OnPaint();
    		CEdit* pBtn = (CEdit*)GetDlgItem(10011);//必须进行强制类型转换
    		HWND hBtn = pBtn->GetSafeHwnd();
    		::SetFocus(hBtn);
    		//PostMessage(WM_KEYDOWN, 85, 85);
    		::keybd_event(85, 0, 0, 0);
    		::keybd_event(85, 0, KEYEVENTF_KEYUP, 0);
    		Sleep(100);
    		count = 1;
    		OnPaint();
    	}
    	CView::OnLButtonUp(nFlags, point);
    	
    }
    

    下面演示一下程序效果:

    实现软键盘会需要你准备很多材料,并且代码片段也很多,这对初学者可能有些困难。如果你想学习MFC,那么你可以从简单的做起,例如学习一下MFC的框架结构,这会帮助你更好地理解MFC的工作原理。

    Best Regards,

    Suarez Zhou


    2019年8月21日 9:29
  • 大佬您好,您说的对,作为一个初学者,一开始弄的确是很困难。在看了鼠标移动到微软键盘上的效果之后,的确是像您说的那样,虽然我现在不明白,不管怎么说还是谢谢您为我解答,这些东西还是等我学了一些MFC之后再来看吧,大佬有什么推荐的书籍嘛,再次感谢
    2019年8月22日 1:03
  • 你好,

    鉴于你的情况,可能《深入浅出MFC》更适合你,当然Microsoft Docs里也有很多相关资料可以查询。链接如下:

    https://docs.microsoft.com/zh-cn/cpp/mfc/mfc-desktop-applications?view=vs-2019

    如果你的问题得到解决,欢迎你标记有价值的回复为正确答案,这会帮助到其他社区成员。

    Best Regards,

    Suarez Zhou

    2019年8月22日 1:35
  • 嗯嗯,谢谢大佬
    2019年8月22日 3:24
  • 你好,

    如果这个问题已经解决,请将你认为有价值的回复标记为答案,这会帮助其他有相同问题的社区成员更快地找到解决方案,谢谢。

    Best Regards,

    Suarez Zhou

    2019年8月22日 5:33
  • 大佬有没有您第一个方案的可运行代码
    2019年8月28日 1:10
  • 你好,

    第一个方案?通过控件ID得到控件的范围,以点击事件的点击点的位置和控件范围比较判定鼠标点击是否在控件上,然后决定是否要发送键盘消息。你是指的这个方案吗?这个是我没有验证,这个方案也会产生错误。不建议从这个想法深入来解决问题。

    另外MSDN论坛倡导一个帖子一个问题。这个帖子已经标记答案了,建议新开一个帖子提问,将你的需求或者问题详细描述下,会有更多的社区工作者参与到你的新问题的回答中,同时这也会提高其他社区成员的阅读体验。

    Best Regards,

    Suarez Zhou 


    2019年8月28日 2:13
  • 那第二个能不能看看
    2019年8月28日 3:07
  • 你好,

    第二个我已经将其上传至OneDrive,链接如下。图片资源文件都已包含,仅供参考。

    https://1drv.ms/u/s!AqHheSBJb5QHjyXwMzEjPbX4d7vx?e=Zp7c61

    你的VS和SDK版本有可能与我不一样,所以程序编译前应该在项目属性设置里更改这两项。

    另外下回提问时希望能新开一个帖子,这个问题已经被标记为Answered。在帖子下继续回复问题是违反论坛规则的。

    Best Regards,

    Suarez Zhou

    2019年8月28日 5:58
  • 链接用不了啊。
    2019年8月28日 15:07
  • 你好,

    请问是为什么用不了,链接访问失败吗?OneDrive在国内是可以访问的,应该不存在这种问题。还是没有账号?用微软账号就可以了,微软账号注册也很简单。

    Best Regards,

    Suarez Zhou

    2019年8月29日 2:05
  • 您好,点击链接无法显示网页,我有微软账号
    2019年8月29日 2:23
  • 你好,

    测试发现好像部分国内网络无法访问OneDrive。由于限制,我无法贴出OneDrive以外的文件链接,所以可能需要你想办法去访问这个链接了。十分不好意思,对于这块内容我无法提供进一步的技术支持了。

    Best Regards,

    Suarez Zhou

    2019年8月29日 2:31
  • 非常感谢您对我的帮助,我会想办法解决的,谢谢
    2019年8月29日 2:34