本帖最后由 wlq390934605 于 2018-3-26 13:15 编辑
今天有几分钟空闲;;
继续更, 继续更吧;
;
那就先说一下, 原版的下地址: http://www.neqee.com/content/?226.html; emWin 2天速成实例教程012_基于STM32单片机的全键盘中文汉字拼音输入法;
;
原版虽然能用, 但BUG也多, 不支持多种控件, 不支持控件识别, 运行效率低, 更不能自动弹出;
;
所以原版仅供参考, 原版使用消息法处理, 效率太低, 故更为 流水线式处理法; (注: EmWin 在某一时刻,仅可能出现一个操作, 这是前提;);
;
回调函数如下:
;
static const char keyCAP[] = {
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P',
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', '_',
'Z', 'X', 'C', 'V', 'B', 'N', 'M', 0};
static const char keyLOW[] = {
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p',
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', '_',
'z', 'x', 'c', 'v', 'b', 'n', 'm', 0};
static const char key123[] = {
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
'!', '@', '%', '*', '(', ')', '_', '-', '+', '=',
'/', ':', ';', '"', ',', '.', '?', 0};
static void _cbDialog(WM_MESSAGE * pMsg) {
WM_HWIN hItem;
int NCode;
int ID_Num, Id, i, temp;
char charBUFF[512], tempBUFF[128]; //获取文本输入缓冲区
static int *pbuffPY[64];
static char **pstrPY=(char **)&pbuffPY[0];
char *pstrTEMP;
static unsigned char capsKEY = 0, inputTYPE = 0;
WM_MESSAGE Message;
switch (pMsg->MsgId) {
case WM_INIT_DIALOG:
capsKEY = 0, inputTYPE = 0;
hItem = pMsg->hWin;
WINDOW_SetBkColor(hItem, (0x00C0C0C0));
// Initialization of 'ping'
TEXT_SetTextAlign(WM_GetDialogItem(pMsg->hWin, ID_TEXT_0), GUI_TA_LEFT | GUI_TA_VCENTER);
TEXT_SetText(WM_GetDialogItem(pMsg->hWin, ID_TEXT_0), "");
// Initialization of '1'
for(i=ID_TEXT_1; i<=ID_TEXT_9; i++)
{
hItem = WM_GetDialogItem(pMsg->hWin, i);
TEXT_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
TEXT_SetFont(hItem, &GUI_FontHZ16);
TEXT_SetText(hItem, "");
}
for(ID_Num = ID_BUTTON_0;ID_Num <= ID_BUTTON_34;ID_Num++)
{
BUTTON_SetFont(WM_GetDialogItem(pMsg->hWin, ID_Num), &GUI_Font16_ASCII); //所有键字体设置
BUTTON_SetFocussable(WM_GetDialogItem(pMsg->hWin, ID_Num), 0); //清除所有键的 焦点
}
break;
case WM_NOTIFY_PARENT:
Id = WM_GetId(pMsg->hWinSrc);
NCode = pMsg->Data.v;
switch(Id) {
//case ID_TEXT_0:
// break; //ID_TEXT_0 不参与输入法处理
case ID_TEXT_1:
case ID_TEXT_2:
case ID_TEXT_3:
case ID_TEXT_4:
case ID_TEXT_5:
case ID_TEXT_6:
case ID_TEXT_7:
case ID_TEXT_8:
case ID_TEXT_9: /*** TEXT_1 --TEXT_2 与下面的 BUTTON 功能合并 ***/
case ID_BUTTON_0: // Notifications sent by 'q'
case ID_BUTTON_1: // Notifications sent by 'w'
case ID_BUTTON_2: // Notifications sent by 'e'
case ID_BUTTON_3: // Notifications sent by 'r'
case ID_BUTTON_4: // Notifications sent by 't'
case ID_BUTTON_5: // Notifications sent by 'y'
case ID_BUTTON_6: // Notifications sent by 'u'
case ID_BUTTON_7: // Notifications sent by 'i'
case ID_BUTTON_8: // Notifications sent by 'o'
case ID_BUTTON_9: // Notifications sent by 'p'
case ID_BUTTON_10: // Notifications sent by 'a'
case ID_BUTTON_11: // Notifications sent by 's'
case ID_BUTTON_12: // Notifications sent by 'd'
case ID_BUTTON_13: // Notifications sent by 'f'
case ID_BUTTON_14: // Notifications sent by 'g'
case ID_BUTTON_15: // Notifications sent by 'h'
case ID_BUTTON_16: // Notifications sent by 'j'
case ID_BUTTON_17: // Notifications sent by 'k'
case ID_BUTTON_18: // Notifications sent by 'l'
case ID_BUTTON_20: // Notifications sent by 'z'
case ID_BUTTON_21: // Notifications sent by 'x'
case ID_BUTTON_22: // Notifications sent by 'c'
case ID_BUTTON_23: // Notifications sent by 'v'
case ID_BUTTON_24: // Notifications sent by 'b'
case ID_BUTTON_25: // Notifications sent by 'n'
case ID_BUTTON_26: // Notifications sent by 'm' /*** 26键_按键功能合并 :Stop ***/
case ID_BUTTON_27: // Notifications sent by '<-' /*** 按键功能合并 ***/
case ID_BUTTON_28: // Notifications sent by '->' /*** 按键功能合并 ***/
case ID_BUTTON_19: // Notifications sent by '_' /************************ 此处为多余 **************************/
case ID_BUTTON_29: // Notifications sent by 'Space' (' ')
case ID_BUTTON_30: // Notifications sent by 'Enter'
case ID_BUTTON_31: // Notifications sent by '<Back' (<--)
case ID_BUTTON_32: // Notifications sent by 'Caps' /*** 结尾不始用 break; 按键'Caps' 'En' 功能合并 ***/
case ID_BUTTON_33: // Notifications sent by 'EN'
switch(NCode) {
case WM_NOTIFICATION_CLICKED:
break;
case WM_NOTIFICATION_RELEASED:
Id = WM_GetId(pMsg->hWinSrc); //获取 操作按键的Id;
/*********************************** ID_BUTTON_0 -- ID_BUTTON_26 功能区 ***********************************/
if(Id >= ID_BUTTON_0 && Id <= ID_BUTTON_26) //26键 发生了操作
{
if(inputTYPE==0 || inputTYPE==1 || capsKEY) //goto gotoASCII; || goto gotoSYMBOL; || goto gotoPING;
{
BUTTON_GetText(pMsg->hWinSrc, &charBUFF[0], sizeof(charBUFF));
GUI_StoreKeyMsg(charBUFF[0], 1); //将按键存储到EMWIN(capsKEY //存储按键到EMWIN并退出)
GUI_StoreKeyMsg(charBUFF[0], 0);
break;
}
else if(inputTYPE == 2 && capsKEY == 0) //'Ch' 中文输入
{
TEXT_GetText(WM_GetDialogItem(pMsg->hWin, ID_TEXT_0), &charBUFF[0], sizeof(charBUFF));
BUTTON_GetText(pMsg->hWinSrc, &tempBUFF[0], sizeof(tempBUFF));
strcat(charBUFF, tempBUFF); //connect string
}
}
/*********************************** ID_TEXT_1 -- ID_TEXT_9 显示区 ***********************************/
if(Id >= ID_TEXT_1 && Id <= ID_TEXT_9) //9 个汉字显示TEXT 发生了操作
{
if(inputTYPE == 2 && capsKEY == 0) //'Ch' 中文输入, 才可以操作
{
if(TEXT_GetText(WM_GetDialogItem(pMsg->hWin, Id), &tempBUFF[0], sizeof(tempBUFF)) == 0) break;
/*** EmWin 各种小工具 汉字文本, 修改接口 ***/
if(WindowSKB_TypeFLAG == 1) /*** EDIT ***/
{
EDIT_GetText(hItem=WM_GetFocussedWindow(), &charBUFF[0], sizeof(charBUFF));
strcat(charBUFF, tempBUFF);
EDIT_SetText(hItem, &charBUFF[0]);
}
else if(WindowSKB_TypeFLAG == 2) /*** MULTIEDIT ***/
{
MULTIEDIT_GetText(hItem=WM_GetFocussedWindow(), &charBUFF[0], sizeof(tempBUFF));
strcat(charBUFF, tempBUFF);
MULTIEDIT_SetText(hItem, &charBUFF[0]);
}
memset(charBUFF, 0, sizeof(charBUFF)); //汉字上屏之后, 清空输入,并重新更新显示与计算
}
}
/*****************************************************************************************************/
/*****************************************************************************************************/
if(Id == ID_BUTTON_19) // Notifications sent by '_' /************************ 此处为多余 **************************/
{
BUTTON_GetText(pMsg->hWinSrc, &charBUFF[0], sizeof(charBUFF));
GUI_StoreKeyMsg(charBUFF[0], 1);
GUI_StoreKeyMsg(charBUFF[0], 0);
break;
}
if(Id == ID_BUTTON_29) // Notifications sent by 'Space' (' ')
{
GUI_StoreKeyMsg(GUI_KEY_SPACE, 1);
GUI_StoreKeyMsg(GUI_KEY_SPACE, 0);
break;
}
if(Id == ID_BUTTON_30) // Notifications sent by 'Enter'
{
GUI_StoreKeyMsg(GUI_KEY_ENTER, 1);
GUI_StoreKeyMsg(GUI_KEY_ENTER, 0);
break;
}
if(Id == ID_BUTTON_31) // Notifications sent by '<Back' (<--)
{
/*** 中文, Caps == 0; ID_TEXT_0有文本; 禁用退格 (退格用来清除TEXT控件一个字符) ***/
i = TEXT_GetText(WM_GetDialogItem(pMsg->hWin, ID_TEXT_0), &charBUFF[0], sizeof(charBUFF));
if((inputTYPE==2) && !capsKEY && i)
{
charBUFF[i-1] = 0; //删除文本输入缓冲区最后一个字符
}
if(((inputTYPE!=2)) || capsKEY || !i)
{
GUI_StoreKeyMsg(GUI_KEY_BACKSPACE, 1);
GUI_StoreKeyMsg(GUI_KEY_BACKSPACE, 0);
break;
}
}
/*****************************************************************************************************/
/*** 中英文/符号 键盘切换区 ***/
if(Id == ID_BUTTON_32) /*** 确认是否 操作了键 'Caps' ***/
{
if(inputTYPE ==1) break; //无视 '123' 数字/符号键下,Caps 的操作
capsKEY = !capsKEY; //切换 Caps 操作标志
if(capsKEY) BUTTON_SetTextColor(pMsg->hWinSrc, BUTTON_CI_UNPRESSED, GUI_RED); //当前按键变红
else BUTTON_SetTextColor(pMsg->hWinSrc, BUTTON_CI_UNPRESSED, GUI_BLACK); //变灰
}
else if(Id == ID_BUTTON_33) /*** 确认是否 操作了键 'En' ***/
{
inputTYPE = (inputTYPE >= 2) ? 0 : (inputTYPE+1); //键盘类型循环切换
capsKEY = 0; //只有EN 有操 作 capsKEY 状态清零
BUTTON_SetTextColor(WM_GetDialogItem(pMsg->hWin, ID_BUTTON_32), BUTTON_CI_UNPRESSED, GUI_BLACK);//只要En有操作, Caps就变灰;
/*** 切换 En 键盘标记 ***/
if(inputTYPE == 0) BUTTON_SetText(pMsg->hWinSrc, "En"); //英文键盘标记
else if(inputTYPE == 1) BUTTON_SetText(pMsg->hWinSrc, "123"); //数字符号键盘标记
else BUTTON_SetText(pMsg->hWinSrc, "Ch"); //中文键盘标记
}
if(Id == ID_BUTTON_32 || Id == ID_BUTTON_33) //仅 中英文切换 和 'CapsKEY' 可以进入
{
/*** inputTYPE = 2_中文; 1_数字/符号; 0_英文; ***/
for(ID_Num=ID_BUTTON_0; ID_Num<=ID_BUTTON_26; ID_Num++)
{
/*** 先设置 颜色, 后设置 文本内容 ***/
if(inputTYPE == 2 && capsKEY == 0)
BUTTON_SetTextColor(WM_GetDialogItem(pMsg->hWin, ID_Num), BUTTON_CI_UNPRESSED, GUI_RED); //红色
else
BUTTON_SetTextColor(WM_GetDialogItem(pMsg->hWin, ID_Num), BUTTON_CI_UNPRESSED, GUI_BLACK); //黑色
/*** 按键 显示 文本设置 ***/
if(inputTYPE==0 || inputTYPE==2) //英文键盘 "En" || //中文键盘 "Ch"
{
if(capsKEY == 0) charBUFF[0] = keyLOW[ID_Num-ID_BUTTON_0]; //小写键盘
else if(capsKEY == 1) charBUFF[0] = keyCAP[ID_Num-ID_BUTTON_0]; //大写键盘
}
else if(inputTYPE == 1) charBUFF[0] = key123[ID_Num-ID_BUTTON_0]; //数字/符号键盘 "123"
charBUFF[1] = 0; //添加 字符串结束符
BUTTON_SetText(WM_GetDialogItem(pMsg->hWin, ID_Num), &charBUFF[0]); //文本载入按键
}
memset(charBUFF, 0, sizeof(charBUFF)); //切换键盘之后, 清空输入,并重新更新显示与计算
}
/*****************************************************************************************************/
/*****************************************************************************************************/
/*** 拼音输入法 处理区 ***/
if((inputTYPE==2 && capsKEY==0) || Id==ID_BUTTON_32) //'Ch' 中文输入 (给CapsKEY 开一条通道)
{
if(Id != ID_BUTTON_27 && Id != ID_BUTTON_28) //BUTTON_27--28 从此处跳过; 进入后续操作
{
TEXT_SetText(WM_GetDialogItem(pMsg->hWin, ID_TEXT_0), &charBUFF[0]); //TEXT_0 显示设置, 公共资源
/*** 拼音输入法处理 ***/
for(i=0; i<sizeof(pbuffPY)/4; i++) pbuffPY = 0; //清空指针 数组
pstrPY = (char **)&pbuffPY[0]; //保存 指针数组 首地址
pstrTEMP = (char *)PYSearch(&charBUFF[0]); //使用拼音 输入法, 得到汉字索引头 指针
//每9个汉字储存一个指针到pbuffPY
/*** 汉字索引非空 && 索引有内容 && 将索引指针载入指针数组, (直至索引空 || 无内容 || BUFF满) ***/
for(i=0; pstrTEMP && *pstrTEMP && (i<sizeof(pbuffPY)/4-1); i++)
{
pbuffPY = (int *)pstrTEMP; //将索引载入指针数组, 间隔9个汉字字符
//pstrTEMP移动9个汉字
for(temp=ID_TEXT_1; temp<=ID_TEXT_9; temp++) //往后偏移 9个字符 (支持任何编码形式)
{
/*** 计算每次 9个字符长度实际偏移 (支持任何编码形式) ***/ //使用'pfGetCharSize'来计算一个汉字的字节数
pstrTEMP = pstrTEMP + GUI_pUC_API->pfGetCharSize(pstrTEMP);
if(!pstrTEMP || !*pstrTEMP) break; //指针空, 无内容跳出
}
}
}
else if(Id == ID_BUTTON_27) //'<-'
{
/*** 预操作测试是否有内容 && 当前首地址与保存的是否一样 ***/
if(*(pstrPY-1) && (pstrPY != (char **)&pbuffPY[0])) pstrPY--; //当前首地址偏移
}
else if(Id == ID_BUTTON_28) //'->'
{
/*** 预操作测试是否有内容 && 当前首地址与保存的是否一样 ***/
if(*(pstrPY+1) && (pstrPY!=(char **)&pbuffPY[sizeof(pbuffPY)/4-1])) pstrPY++;
else pstrPY = (char **)&pbuffPY[0]; //否则载入保存首地址
}
/*****************************************************************************************************/
/*****************************************************************************************************/
/*** 输入法, 结果显示区 ***/
//将字符显示至 ID_TEXT_1~ID_TEXT_9
for(pstrTEMP = *pstrPY, i=ID_TEXT_1; i<=ID_TEXT_9; i++)
{
memset(&tempBUFF[0], 0, sizeof(tempBUFF));
if(!pstrTEMP || !*pstrTEMP) {TEXT_SetText(WM_GetDialogItem(pMsg->hWin, i), ""); continue;} //(空||无内容)清空当前文本框; 仅结束本次循环
memcpy(&tempBUFF[0], pstrTEMP, temp = GUI_pUC_API->pfGetCharSize(pstrTEMP)); //temp_汉字的字节数 (支持任何编码)
TEXT_SetText(WM_GetDialogItem(pMsg->hWin, i), &tempBUFF[0]); //汉字更新至文本框
pstrTEMP = pstrTEMP + temp; //偏移一个汉字字符
}
}
}
/*****************************************************************************************************/
/*****************************************************************************************************/
break;
case ID_BUTTON_34: // Notifications sent by 'Esc'
switch(NCode) {
case WM_NOTIFICATION_CLICKED:
break;
case WM_NOTIFICATION_RELEASED:
WM_HideWindow(pMsg->hWin); //隐藏窗口
// WM_SetFocus(WM_HBKWIN); //焦点移至桌面
//renew all keys include caps
inputTYPE = (inputTYPE <= 0) ? 2 : (inputTYPE-1); //重新打开, 仅能是 'En' 或 '123'
Message.hWinSrc = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_33);
Message.MsgId = WM_NOTIFY_PARENT;
Message.Data.v = WM_NOTIFICATION_RELEASED;
WM_SendMessage(pMsg->hWin, &Message);
}
break;
}
break;
case WM_PAINT:
{
WM_BringToTop(pMsg->hWin); //自动将键盘窗口置顶
}
break;
default:
WM_DefaultProc(pMsg);
break;
}
}
|