miniGUI源码分析:软键盘实现原理

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

软键盘文件目录

文件说明
softkeywindow.c软键盘主窗口文件,包含窗口创建、窗口过程函数等
common.c窗口通用处理函数文件,包含按键消息处理函数、字符窗体处理函数等
resource.c图片资源管理文件,包含图片资源的加载和释放等
en_kbd.c英文键盘文件,不同键盘分别在不同的文件中,例如pinyin_kbd.c、num_kbd.c
size_*.h窗口和按键坐标定义文件
softkeyboard.h结构体及函数声明文件

软键盘实现原理

miniGUI软键盘根本上是由图片和按键坐标配合实现,不同的键盘需配置不同的图片和与之对应窗口坐标。窗口以整张图片作为背景,在点击和移动鼠标时,根据鼠标在窗口的位置与坐标判断执行对应的操作,窗口中的所有按键都是靠坐标来实现的。
在这里插入图片描述

软键盘窗口一共分为3个区域,view_window,stroke_window,key_window

  • key_window为键盘图片中的按键区域,处理按键的显示刷新
  • stroke_window为输入的字符显示区,例如拼音输入,会在此区域显示输入的字母
  • view_window为候选词显示区,例如拼音输入,会在此区域显示候选字

符号键盘则没有stroke_window和view_window

_md_key_t结构体

  • bound为单个键的坐标,包括按键的具体位置和宽高
  • key_char为按键中的字符,功能键则为空
  • scan_code为对应的键值,标记该键的具体功能
  • style用来区分是字符键还是功能键
  • update为按键刷新函数,模拟按钮的点击效果等。
typedef struct _md_key_t {
    /* the corrosponding rect of the key pad */
    RECT bound;
    /* the corresponging character of this key pad
     * such as 'a','b' etc
     */
    char key_char;
    /* the correcponging scancode of this key pad.
     * such as SCANCODE_F1~F3,BACKSPACE,ENTER,UP,DOWN,LEFT,RIGHT...
     */
    int scan_code; 
    /* the style of this key pad. 
     * KEY_CHAR indaces the keypad is a character key pad
     * KEY_FUNC indaces the keypad is a functional key pad
     */
    int style;
    /* private data for method update */
    void * data;
    
    /* this function is used to update the rect of key*/
    void (*update)(struct _md_key_t * key, HWND hwnd);
} md_key_t;

显示和隐藏

软键盘线程在主窗口创建时创建,加载图片资源后调用CreateMainWindow创建软键盘窗口

  • 显示
    用户在点击控件时,通过客户区默认鼠标处理函数DefaultMouseMsgHandler接收鼠标左键点击消息,通过判断控件的类型及风格,给软键盘窗口句柄发送MSG_IME_SETSTATUS消息设置软键盘类型,最后显示软键盘。
static GINT DefaultMouseMsgHandler (PMAINWIN pWin, int message, WPARAM flags, int x, int y)
{
 	pUnderPointer = wndMouseInWhichControl (pWin, x, y, &UndHitCode);
	switch (message) 
	{
	case MSG_LBUTTONDOWN:
		if (__mg_ime_wnd)
		{
			if (message == MSG_LBUTTONDOWN)
			{
				LWORD dwStyleEdit = GetWindowStyle((HWND)pUnderPointer);
				SendNotifyMessage (__mg_ime_wnd, MSG_IME_SETSTATUS,IME_STATUS_SWITCH, IME_SWITCH_TOEN);
				
				if (!IsWindowVisible(__mg_ime_wnd))
				{
					open_ime_window ((PMAINWIN)pUnderPointer, TRUE, 0);
				}
			}
		}
	}
}
  • 隐藏
    用户在点击控件外区域时产生非客户区鼠标点击消息,非客户区默认鼠标处理函数DefaultNCMouseMsgHandler接收左键点击消息,隐藏软键盘窗口。
static GINT DefaultNCMouseMsgHandler(PMAINWIN pWin, int message, int location, int x, int y)
{
	switch (message)
	{
		case MSG_NCLBUTTONDOWN:
			open_ime_window (pWin, FALSE, 0);
	}
}

输入和切换

鼠标点击键盘后发送MSG_LBUTTONDOWN消息到SoftKeyWinProc窗口过程函数,调用对应键盘的消息处理函数keyboard->proceed_msg,并根据点击位置循环查找对应按键信息,最终根据不同按键分别处理。

static GINT SoftKeyWinProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
	switch (message) {
	case MSG_LBUTTONDOWN:
		switch (pdata->keyboard->proceed_msg(pdata->keyboard, hWnd, message, wParam, lParam)) {
		//键盘切换
		case AC_CHANGE_KBD: {
			int y;
			POINT p; 
            
			p.x = LOSWORD(lParam);
			p.y = HISWORD(lParam);

			md_key_t* key = pdata->keyboard->key_window->get_key(pdata->keyboard->key_window, p);

			if (!key)
			    break;
                
			/* english */
			if (key->scan_code == SCANCODE_TOEN){
			    y = 0;   
			    pdata->ime_status_language = IME_LANGUAGE_LATIN;
			}
			/* pinyin */ 
			if (key->scan_code == SCANCODE_TOPY) {
			    y = 1;   
			    pdata->ime_status_language = IME_LANGUAGE_ZHCN;
			}
			
			/* 123 */ 
			if (key->scan_code == SCANCODE_TONUM) {
			    y = 2;   
			    pdata->ime_status_language = IME_LANGUAGE_LATIN;
			}
			/* oprator */ 
			if (key->scan_code == SCANCODE_TOOP)   {
			    y = 3;  
			    pdata->ime_status_language = IME_LANGUAGE_LATIN;
			}
			
			/*clear old state */
			pdata->keyboard->clear(pdata->keyboard);
			pdata->current_board_idx = status_table[pdata->current_board_idx][y];
			pdata->keyboard = keyboard[pdata->current_board_idx];
			
			SendMessage(hWnd, MSG_ERASEBKGND, 0, 0L);
			softkey_reset();
			return 0;
		}
		//字符输入
		case AC_SEND_MSG:
#if defined(_MGRM_PROCESSES) && (MINIGUI_MAJOR_VERSION > 1) && !defined(_STAND_ALONE)
	            Send2ActiveWindow(mgTopmostLayer, 
	                pdata->keyboard->action.message,
	                pdata->keyboard->action.wParam, 
	                pdata->keyboard->action.lParam);
#elif defined(_MGRM_THREADS) && !defined(_STAND_ALONE)
	            PostMessage(pdata->target_hwnd, 
	                pdata->keyboard->action.message,
	                pdata->keyboard->action.wParam, 
	                pdata->keyboard->action.lParam);
#endif
		    return 0;
	return 0;
	}
}

static int en_proc_msg(key_board_t* key_board, HWND hwnd, int message, WPARAM wParam, LPARAM lParam)
{
	switch (message) {
		case MSG_LBUTTONDOWN:
			p.x = LOSWORD(lParam);
			p.y = HISWORD(lParam);
			lbuttondown = 1;
			key_board->action.operation = AC_NULL; 

			if (PtInRect(&key_board->view_window->bound, p.x, p.y)) {
				vw_proceed_hit(hwnd, key_board->view_window,
						key_board->stroke_window, &key_board->action,
						TRUE, p, CN, key_board->ime);
				break;
			}

			if (PtInRect(&key_board->key_window->bound, p.x, p.y)) {
				key = key_board->key_window->get_key(key_board->key_window, p);
				if (key == NULL) {
					key_board->action.operation = AC_NULL; 
					break;
				}
                
                kw_proceed_hit(hwnd, key_board->view_window,
						key_board->stroke_window, key, &key_board->action,
						TRUE, p, EN, key_board->ime, wParam, lParam);
                key_down = key;
                break;
			}
	}
}
  • 键盘切换
    pdata->keyboard->proceed_msg在英文键盘下对应en_proc_msg,接收MSG_LBUTTONDOWN消息后,判断当前点击位置为按键区,通过get_key获取按键信息,并传入kw_proceed_hit函数,当获取的按键信息key->scan_code为SCANCODE_TONUM~SCANCODE_TOOP之间时,返回AC_CHANGE_KBD。最后SoftKeyWinProc通过与status_table二维数组比较,确定将要切换的键盘,完成键盘的切换。

  • 字符输入
    当获取的按键信息key->style为KEY_PAD_CHAR时,判断为字符键,则kw_proceed_hit函数返回以下信息,ch为按键字符,最后发送消息给目标控件。
    action->operation = AC_SEND_MSG;
    action->message = MSG_CHAR;
    action->wParam = ch;
    action->lParam = 0;

以上为miniGUI软键盘的基本实现原理,下一篇会说明如何修改美化原有的软键盘。

visual c++ vc++制作Windows软键盘 屏幕键盘.zip vc++制作Windows软键盘 屏幕键盘.zip 立即下载

相关推荐

miniGUI源码分析软键盘界面美化

上一篇说到,miniGUI软键盘根本上是由图片和按键坐标配合实现,若想修改和软键盘,则需替换图片和修改对应坐标,新增键盘同理。 图片资源在mgiresource.c文件中,skbRes中为所有的键盘图片资源,同名图片可直接替换,新增图片则需在skbRes中添加。坐标则需根据图片位置修改以下宏定义。 hong hanyi SKB_WIN_W/SKB_WIN_H 键盘的宽高 SKB_CLOSE_L/SKB_CLOSE_T / SKB_CLOSE_R/SKB_CLOSE_B 关闭键盘按钮的坐标

secretii的博客 807

简单的MiniGUI软键盘

由于已经购买mGi模块,故而自己写的这个用不着了,留在这里做个记念吧。以下是关键代码,其实思想蛮简单,就是发送消息给输入法窗口就万事大吉了。但是有个最重要的bug就是中文输入无法选择所有的汉字,估计要改一下minigui输入法的源码,mGi的软键盘是利用了两行。示例图如下,很简陋,如果经过美化,可以做到很漂亮。 #include "common.h" #define ITEM_N

jia0511的专栏 1213

QT 5.5.1使用虚拟键盘,适用于arm-linux

3、将该文件复制到开发板qt的plugins/platforminputcontexts文件夹下,若无platforminputcontexts文件夹,则手动建立。查看文件链接,复制原文件,如下图所示,原文件为libtgtsmlInputContextPlugin.so.1.0.0,即为所需要的文件。其中,armA64-qt为移植到A64开发板的qt文件夹,移植教程请自行搜索。4. 将plugin下的dict文件夹放到工程编译生成的APP同一目录下。一、在ububntu打开工程,配置构建套件,如下图所示。

qq_40067649的博客 3024

MiniGUI源码分析——MiniGUIMain的奥秘

接下来,通过剖析MiniGUI的最简单的例程,来详细说明MiniGUI程序是如何创建和运行的。 这个例程,可以从很多地方得到,凡是接触过MiniGUI的朋友,首先接触的便是这个例子,为了方便大家阅读,贴在下面 /* ** $Id: helloworld.c,v 1.38 2007-10-25 07:56:45 weiym Exp $ ** ** Listing 2.1 ** **

曾经沧海 3518

MiniGUI源码分析:GDI(1)-- GDI概览及Surface

上一篇:MiniGUI源码分析--Helloworld(3):消息概览 从本章开始,将逐步介绍MiniGUI部分GDI GDI(Graphics Device Interface)是对绘图接口的描述,是MiniGUI的核心组成部分之一。 GDI虽然是GUI的基础,但是,它实际上不太适合作为GUI的组成部分之一的。因为GUI的核心功能在用户交互上,而不是如何绘制上。对M

doon的专栏 5072

MiniGUI源码分析——GDI概览及Surface

GDI(Graphics Device Interface)是对绘图接口的描述,是MiniGUI的核心组成部分之一。 GDI虽然是GUI的基础,但是,它实际上不太适合作为GUI的组成部分之一的。因为GUI的核心功能在用户交互上,而不是如何绘制上。对MiniGUI来说,GDI是成也萧何败萧何:MiniGUI内置的GDI使得MiniGUI更紧凑和高效,但是由于其功能受限,使得MiniGUI

曾经沧海 1648

minigui[基础篇][8]—— 键盘和鼠标之键盘

minigui手册阅读

qq_43601873的博客 593

minigui[基础篇][9]—— 键盘和鼠标之鼠标

minigui手册阅读

qq_43601873的博客 531

android软键盘的用法总结

1.软键盘的显示原理        软键盘其实是一个Dialog。InputMethodService为我们的输入法创建了一个Dialog,并且对某些参数进行了设置,使之能够在底部或者全屏显示。当我们点击输入框时,系统会对当前的主窗口进行调整,以便留出相应的空间来显示该Dialog在底部,或者全屏。 2.活动主窗口调整        Android定义了一个属性windowSoftInput

翊轩LeOn 1443

MiniGUI更换键盘皮肤

前言 MiniGUI原来的键盘GUI已经有点不符合现在的需求,所以需要定制一套皮肤,根据我定制皮肤的过程,写一遍流程文档,做一下笔记,为以后再定制皮肤提供参考,先看一下定制好的皮肤 录制的色彩有点失真,看一下截图 1. 皮肤资源位置 在libmgi-2.0.4/src/softkeyboard/softkeyboard/分辨率,目录下有一些图片资源,里面是图片转为十六进制的c文件,总共需要替换...

逐梦的博客 2160

minigui[基础篇][14]—— 界面外观及特效

minigui手册阅读

qq_43601873的博客 1212

使用MiniGUI

使用MiniGUI MiniGUI是一个嵌入式设备上使用的类似于QT的图形界面,sorceforge上有开源的1.6.10版,不过最新版的已经到了3点多了,但不开源,所以咱还是老老实实的用1.6.10版吧: 1. 在http://sourceforge.net/projects/minigui/files/minigui/GPL-V1.6.10/下载MiniGUI 1

htttw的专栏 2120

MiniGUI 编程

Step 1:使用 MiniGUI 创建窗口 首先回答一个问题:什么是 MiniGUI。简而言之,对用户来说,MiniGUI 就是在控制台上为用户提供一个图形接口,使用户能够利用它提供的函数创建图形界面程序。MiniGUI 占用非常少的系统资源,适用于嵌入式系统应用程序。 出于历史的原因,在开发 MiniGUI 的时候,模拟了 Windows 系统的某些机制,因此如果用户非常...

weixin_34220963的博客 245

minigui[基础篇][1]——第一个helloword程序

minigui手册阅读和学习

qq_43601873的博客 580

minigui[基础篇][5]—— 控件与控件类

minigui手册阅读

qq_43601873的博客 1034

minigui[基础篇][7]—— 菜单

minigui手册阅读

qq_43601873的博客 533

MiniGUI学习笔记

第一章.嵌入式GUI系统概述关于操作系统和上层软件的关系,某些操作系统被称为内核空间(kernel space),而操作系统以上的部分被称为用户空间(user space)。按照功能,操作系统以上的部分可以分为中间件和上层应用两个部分。中间件一般提供了一些相对底层的软件层次的功能。它的实现一般不包括应用程序的逻辑,而是向上层软件提供了各种方便的应用程序接口(API)。GUI系统的移植实现基础包含输出设备和输入设备两个方面       在学习一个嵌入式GUI特性和功能的时候,需要关注可移植性、稳定性和可靠性、

huangxin8707的专栏 2689

minigui源码学习

前言: 个人习惯学习源码先从编译结构了解代码模块,所以先从编译结构开始了解。 如果编译角度搞不定,就代码开始运行时,各个模块初始化的角度开始了解。 学习源码——编译角度 建立编译平台 使用公司提供的统一编译平台,10.1.74.178 下载源码 git clone https://github.com/VincentWei/minigui.gitminigui 编译 minig...

C_Creator的博客 1182
上一篇: miniGUI源码分析:消息机制
下一篇: miniGUI源码分析:软键盘界面美化
Peel Chen
博客等级 码龄10年 8粉丝 17原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值