Files
player/Project/Src/MyWin/Window/mywin_input.c
2025-07-06 18:46:13 +08:00

615 lines
19 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "mywin_inc.h"
// 定义输入法类型
#define WIN_INPUT_TYPE "WIN_InputStruct"
// 定义输入法按键别名
#define INPUT_BUTTON_Q button[0]
#define INPUT_BUTTON_W button[1]
#define INPUT_BUTTON_E button[2]
#define INPUT_BUTTON_R button[3]
#define INPUT_BUTTON_T button[4]
#define INPUT_BUTTON_Y button[5]
#define INPUT_BUTTON_U button[6]
#define INPUT_BUTTON_I button[7]
#define INPUT_BUTTON_O button[8]
#define INPUT_BUTTON_P button[9]
#define INPUT_BUTTON_A button[10]
#define INPUT_BUTTON_S button[11]
#define INPUT_BUTTON_D button[12]
#define INPUT_BUTTON_F button[13]
#define INPUT_BUTTON_G button[14]
#define INPUT_BUTTON_H button[15]
#define INPUT_BUTTON_J button[16]
#define INPUT_BUTTON_K button[17]
#define INPUT_BUTTON_L button[18]
#define INPUT_BUTTON_Z button[19]
#define INPUT_BUTTON_X button[20]
#define INPUT_BUTTON_C button[21]
#define INPUT_BUTTON_V button[22]
#define INPUT_BUTTON_B button[23]
#define INPUT_BUTTON_N button[24]
#define INPUT_BUTTON_M button[25]
#define INPUT_BUTTON_LEFT button[26]
#define INPUT_BUTTON_RIGHT button[27]
#define INPUT_BUTTON_ESC button[28]
#define INPUT_BUTTON_SHIFT button[29]
#define INPUT_BUTTON_EN button[30]
#define INPUT_BUTTON_123 button[31]
#define INPUT_BUTTON_COMMA button[32]
#define INPUT_BUTTON_SPACE button[33]
#define INPUT_BUTTON_FULLSTOP button[34]
#define INPUT_BUTTON_BACK button[35]
#define INPUT_BUTTON_ENTER button[36]
#include "res/pymb.txt"
static const char *g_keybord_txt = "QWERTYUIOPASDFGHJKLZXCVBNM";
static const char *g_keybord_mini = "qwertyuiopasdfghjklzxcvbnm";
static const char *g_keybord_num[] = {"1234567890-=!@#$%^&*()_+`~",
"[]\\;',./{}|:\"<>?"};
// 在堆中创建一个输入法
WIN_InputStruct *WIN_CreatInput(WIN_WindowStruct *base,
void (*msgLoop)(struct _WIN_WindowStruct *win,
WIN_MsgStruct *msg),
int x, int y, int x_size, int y_size) {
// 重设消息循环
if (msgLoop == 0) {
msgLoop = (void (*)(struct _WIN_WindowStruct *win,
WIN_MsgStruct *msg))INPUT_DefaultMsgLoop;
}
WIN_InputStruct *ret = mymalloc(sizeof(WIN_InputStruct));
// 调用父类的构造函数
if (ret) {
mymemset(ret, 0, sizeof(WIN_InputStruct));
if (0 == WIN_CreatWindowExt((WIN_WindowStruct *)ret, base, msgLoop, x, y,
x_size, y_size)) {
// 创建失败
myfree(ret);
ret = 0;
} else {
// 构造一个
((WIN_WindowStruct *)ret)->winType = WIN_INPUT_TYPE;
((WIN_WindowStruct *)ret)->intercept = 1; // 输入阻塞
((WIN_WindowStruct *)ret)->bkcolor = 0x7700cc;
ret->button_ysize = 30;
int x = 0;
int y = 0;
int x_size = ((WIN_WindowStruct *)ret)->x_size;
int y_size = ((WIN_WindowStruct *)ret)->y_size;
int button_x_size = x_size / 10;
int button_y_size = ret->button_ysize;
int button_x = x;
int button_y = y + y_size - 1 - button_y_size * 5;
ret->pinyin_y = button_y - WIN_GetFontHight(); // 拼音显示位置
// 候选字按键
for (int i = 0; i < 10; i++) {
ret->word[i].x = button_x;
ret->word[i].y = button_y;
ret->word[i].x_size = button_x_size;
ret->word[i].y_size = button_y_size;
button_x += button_x_size;
}
button_x = x;
button_y += button_y_size;
// 字母按键
for (int i = 0; i < 26; i++) {
if (i == 10) {
button_y += button_y_size;
button_x = x + button_x_size / 3;
}
if (i == 19) {
button_y += button_y_size;
button_x = x + button_x_size * 2 / 3;
}
ret->button[i].x = button_x;
ret->button[i].y = button_y;
ret->button[i].x_size = button_x_size;
ret->button[i].y_size = button_y_size;
button_x += button_x_size;
char chars[2] = {0};
chars[0] = g_keybord_txt[i];
mymemcpy(ret->button[i].txt, chars, 2);
}
// 功能按键
ret->INPUT_BUTTON_LEFT.x = button_x;
ret->INPUT_BUTTON_LEFT.y = button_y;
ret->INPUT_BUTTON_LEFT.x_size = button_x_size;
ret->INPUT_BUTTON_LEFT.y_size = button_y_size;
mymemcpy(ret->INPUT_BUTTON_LEFT.txt, "<", 2);
button_x += button_x_size;
ret->INPUT_BUTTON_RIGHT.x = button_x;
ret->INPUT_BUTTON_RIGHT.y = button_y;
ret->INPUT_BUTTON_RIGHT.x_size = button_x_size;
ret->INPUT_BUTTON_RIGHT.y_size = button_y_size;
mymemcpy(ret->INPUT_BUTTON_RIGHT.txt, ">", 2);
button_x = x;
button_y += button_y_size;
ret->INPUT_BUTTON_ESC.x = button_x;
ret->INPUT_BUTTON_ESC.y = button_y;
ret->INPUT_BUTTON_ESC.x_size = button_x_size;
ret->INPUT_BUTTON_ESC.y_size = button_y_size;
mymemcpy(ret->INPUT_BUTTON_ESC.txt, "ESC", 5);
button_x += button_x_size;
ret->INPUT_BUTTON_SHIFT.x = button_x;
ret->INPUT_BUTTON_SHIFT.y = button_y;
ret->INPUT_BUTTON_SHIFT.x_size = button_x_size;
ret->INPUT_BUTTON_SHIFT.y_size = button_y_size;
mymemcpy(ret->INPUT_BUTTON_SHIFT.txt, "SHIFT", 5);
button_x += button_x_size;
ret->INPUT_BUTTON_EN.x = button_x;
ret->INPUT_BUTTON_EN.y = button_y;
ret->INPUT_BUTTON_EN.x_size = button_x_size;
ret->INPUT_BUTTON_EN.y_size = button_y_size;
mymemcpy(ret->INPUT_BUTTON_EN.txt, "EN", 5);
button_x += button_x_size;
ret->INPUT_BUTTON_123.x = button_x;
ret->INPUT_BUTTON_123.y = button_y;
ret->INPUT_BUTTON_123.x_size = button_x_size;
ret->INPUT_BUTTON_123.y_size = button_y_size;
mymemcpy(ret->INPUT_BUTTON_123.txt, "123", 5);
button_x += button_x_size;
ret->INPUT_BUTTON_COMMA.x = button_x;
ret->INPUT_BUTTON_COMMA.y = button_y;
ret->INPUT_BUTTON_COMMA.x_size = button_x_size;
ret->INPUT_BUTTON_COMMA.y_size = button_y_size;
mymemcpy(ret->INPUT_BUTTON_COMMA.txt, ",", 5);
button_x += button_x_size;
ret->INPUT_BUTTON_SPACE.x = button_x;
ret->INPUT_BUTTON_SPACE.y = button_y;
ret->INPUT_BUTTON_SPACE.x_size = button_x_size * 2;
ret->INPUT_BUTTON_SPACE.y_size = button_y_size;
mymemcpy(ret->INPUT_BUTTON_SPACE.txt, " ", 5);
button_x += button_x_size * 2;
ret->INPUT_BUTTON_FULLSTOP.x = button_x;
ret->INPUT_BUTTON_FULLSTOP.y = button_y;
ret->INPUT_BUTTON_FULLSTOP.x_size = button_x_size;
ret->INPUT_BUTTON_FULLSTOP.y_size = button_y_size;
mymemcpy(ret->INPUT_BUTTON_FULLSTOP.txt, ".", 5);
button_x += button_x_size;
ret->INPUT_BUTTON_BACK.x = button_x;
ret->INPUT_BUTTON_BACK.y = button_y;
ret->INPUT_BUTTON_BACK.x_size = button_x_size;
ret->INPUT_BUTTON_BACK.y_size = button_y_size;
mymemcpy(ret->INPUT_BUTTON_BACK.txt, "Back", 5);
button_x += button_x_size;
ret->INPUT_BUTTON_ENTER.x = button_x;
ret->INPUT_BUTTON_ENTER.y = button_y;
ret->INPUT_BUTTON_ENTER.x_size = button_x_size;
ret->INPUT_BUTTON_ENTER.y_size = button_y_size;
mymemcpy(ret->INPUT_BUTTON_ENTER.txt, "ENTER", 5);
button_x += button_x_size;
}
}
return ret;
}
// 键盘切换至字母大写
void INPUT_SetToAscBig(WIN_InputStruct *input) {
// 字母按键
for (int i = 0; i < 26; i++) {
char chars[2] = {0};
chars[0] = g_keybord_txt[i];
mymemcpy(input->button[i].txt, chars, 2);
}
}
// 键盘切换至字母小写
void INPUT_SetToAscMini(WIN_InputStruct *input) {
// 字母按键
for (int i = 0; i < 26; i++) {
char chars[2] = {0};
chars[0] = g_keybord_mini[i];
if (chars[0] == 0)
break;
mymemcpy(input->button[i].txt, chars, 2);
}
}
// 键盘切换至数字
void INPUT_SetToNum(WIN_InputStruct *input) {
// 字母按键
for (int i = 0; i < 26; i++) {
char chars[2] = {0};
chars[0] = g_keybord_num[input->num_symbol_page][i];
if (chars[0] == 0)
break;
mymemcpy(input->button[i].txt, chars, 2);
}
}
// 按键按下
void INPUT_SetPressDown(WIN_InputStruct *input) {
for (int i = 0; i < 37; i++) {
if (POS_InRect(input->button[i].x, input->button[i].y,
input->button[i].x_size, input->button[i].y_size,
input->press_x, input->press_y) == 1) {
input->button[i].press = 1;
input->press_down_index = i;
return;
}
}
for (int i = 0; i < 10; i++) {
if (POS_InRect(input->word[i].x, input->word[i].y, input->word[i].x_size,
input->word[i].y_size, input->press_x,
input->press_y) == 1) {
input->word[i].press = 1;
input->press_down_index_word = i;
return;
}
}
}
// 按键抬起
void INPUT_SetPressUp(WIN_InputStruct *input) {
input->button[input->press_down_index].press = 0;
input->word[input->press_down_index_word].press = 0;
}
// 添加拼音
void INPUT_PinYinAppend(WIN_InputStruct *input) {
int pinyin_len = strlen(input->inputPinyin);
if ((pinyin_len < 10) && input->button[input->press_down_index].press) {
char txt = input->button[input->press_down_index].txt[0];
if (txt < 'a')
txt += 'a' - 'A';
input->inputPinyin[pinyin_len] = txt;
}
}
// 拼音截短
void INPUT_PinYinCut(WIN_InputStruct *input) {
int pinyin_len = strlen(input->inputPinyin);
if (pinyin_len)
input->inputPinyin[pinyin_len - 1] = 0;
}
// 追加输入字符
void INPUT_WordAppend(WIN_InputStruct *input) {
int word_len = strlen(input->inputWords);
if (word_len <
INPUT_WORDS_MAXNUM -
2) // 预留至少可以输入一个汉字的空间,并且最后一位要用来做结尾符
{
input->candidateWord[2] = 0;
int candidate_len = strlen(input->candidateWord);
if (candidate_len == 2) {
mymemcpy(&input->inputWords[word_len], input->candidateWord,
candidate_len + 1);
mymemset(input->candidateWord, 0, 3);
} else if (input->button[input->press_down_index].press) {
input->inputWords[word_len] =
input->button[input->press_down_index].txt[0];
input->inputWords[word_len + 1] = 0;
}
}
}
// 输入字符截短
void INPUT_WordCut(WIN_InputStruct *input) {
int word_len = strlen(input->inputWords);
char *p_txt = input->inputWords;
int reback = 0;
while (*p_txt) {
if (*p_txt & 0x80)
reback = 2;
else
reback = 1;
p_txt += reback;
}
input->inputWords[word_len - reback] = 0;
}
// 比较两个字符串是否相等最多比较str1长度的字符串
static int input_strcmp(const char *str1, const char *str2) {
int len = strlen(str1);
if (len == 0)
return -1;
for (int i = 0; i < len; i++) {
if (str1[i] != str2[i])
return -1;
}
return 0;
}
// 查询候选字符
void INPUT_FindWord(WIN_InputStruct *input) {
for (int i = 0; g_py_index[i].str; i++) {
// if (strcmp ((char *)g_py_index[i].str,input->inputPinyin)==0)
if (input_strcmp(input->inputPinyin, (char *)g_py_index[i].str) == 0) {
input->word_const = g_py_index[i].word;
input->word_page = 0; // 重置到第0页
return;
}
}
input->word_const = 0;
input->word_page = 0; // 重置到第0页
}
// 把待选字符复制到字符按钮中
void INPUT_StorWordButton(WIN_InputStruct *input) {
int i = 0;
if (input->word_const) {
char *word = (char *)input->word_const + input->word_page * 20;
for (; i < 10; i++) {
if (word[i * 2]) {
input->word[i].txt[0] = word[i * 2];
input->word[i].txt[1] = word[i * 2 + 1];
input->word[i].txt[2] = 0;
} else {
break;
}
}
}
{
for (; i < 10; i++) {
input->word[i].txt[0] = 0;
}
}
}
// 功能按键
void INPUT_FunctionKey(WIN_InputStruct *input) {
if (input->INPUT_BUTTON_BACK.press) {
int pinyin_len = strlen(input->inputPinyin);
if (pinyin_len) {
INPUT_PinYinCut(input);
INPUT_FindWord(input);
INPUT_StorWordButton(input);
} else
INPUT_WordCut(input);
} else if (input->INPUT_BUTTON_LEFT.press) {
// 左键
if (input->inputMode == INPUT_MODE_PINYIN) {
if (input->word_page > 0)
input->word_page--;
INPUT_StorWordButton(input);
} else if (input->inputMode == INPUT_MODE_NUM) {
if (input->num_symbol_page > 0)
input->num_symbol_page--;
INPUT_SetToNum(input);
}
} else if (input->INPUT_BUTTON_RIGHT.press) {
// 右键
if (input->inputMode == INPUT_MODE_PINYIN) {
if (input->word_const) {
int str_len = strlen((char *)input->word_const);
if ((input->word_page + 1) * 20 < str_len)
input->word_page++;
INPUT_StorWordButton(input);
}
} else if (input->inputMode == INPUT_MODE_NUM) {
if (input->num_symbol_page < 1)
input->num_symbol_page++;
INPUT_SetToNum(input);
}
} else if (input->INPUT_BUTTON_ESC.press) {
input->exit = 1; // 退出,不保存输入
WIN_SetBlockWinReturn(0, 0, 0);
} else if (input->INPUT_BUTTON_SHIFT.press) {
if (input->inputMode == INPUT_MODE_BIG) {
INPUT_SetToAscMini(input);
input->inputMode = INPUT_MODE_MINI;
} else if (input->inputMode == INPUT_MODE_MINI) {
INPUT_SetToAscBig(input);
input->inputMode = INPUT_MODE_BIG;
}
} else if (input->INPUT_BUTTON_EN.press) {
if (input->inputMode == INPUT_MODE_PINYIN) {
INPUT_SetToAscMini(input);
input->inputMode = INPUT_MODE_MINI;
mymemset(input->inputPinyin, 0, 10); // 清除拼音输入
INPUT_FindWord(input);
INPUT_StorWordButton(input);
mymemset(input->candidateWord, 0, 3);
} else {
INPUT_SetToAscBig(input);
input->inputMode = INPUT_MODE_PINYIN;
}
} else if (input->INPUT_BUTTON_123.press) {
input->inputMode = INPUT_MODE_NUM;
input->num_symbol_page = 0;
INPUT_SetToNum(input);
mymemset(input->inputPinyin, 0, 10); // 清除拼音输入
INPUT_FindWord(input);
INPUT_StorWordButton(input);
mymemset(input->candidateWord, 0, 3);
} else if (input->INPUT_BUTTON_ENTER.press) {
input->exit = 1; // 退出,保存输入
void *retdata = mymalloc(100);
mymemcpy(retdata, input->inputWords, strlen(input->inputWords) + 1);
WIN_SetBlockWinReturn(1, retdata, 100);
myfree(retdata);
}
}
// 按键松开的时候做点什么
void INPUT_DoSomethingPressUp(WIN_InputStruct *input) {
if (input->press_down_index < 26) {
// 是输入按键
if (input->inputMode == INPUT_MODE_PINYIN) {
INPUT_PinYinAppend(input);
INPUT_FindWord(input);
INPUT_StorWordButton(input);
} else {
INPUT_WordAppend(input);
}
} else if ((input->press_down_index >= 32) &&
(input->press_down_index <= 34)) {
// 主界面的标点符号
mymemset(input->inputPinyin, 0, 10); // 清除拼音输入
INPUT_FindWord(input);
INPUT_StorWordButton(input);
mymemset(input->candidateWord, 0, 3);
INPUT_WordAppend(input);
} else {
// 功能按键
INPUT_FunctionKey(input);
// 更新功能按键上显示的字符
if (input->inputMode == INPUT_MODE_PINYIN) {
mymemcpy(input->INPUT_BUTTON_EN.txt, "EN", 3);
} else {
mymemcpy(input->INPUT_BUTTON_EN.txt, "", 3);
}
}
if (input->word[input->press_down_index_word].press) {
// 选择了候选字
mymemcpy(input->candidateWord,
input->word[input->press_down_index_word].txt, 3);
INPUT_WordAppend(input);
mymemset(input->inputPinyin, 0, 10); // 清除拼音输入
INPUT_FindWord(input);
INPUT_StorWordButton(input);
}
}
// 默认绘制函数
void INPUT_DefaultPaint(WIN_InputStruct *input) {
// 使用双缓冲,防止闪烁
int x = 0;
int y = 0;
int x_size = ((WIN_WindowStruct *)input)->x_size;
int y_size = ((WIN_WindowStruct *)input)->y_size -
(((WIN_WindowStruct *)input)->y_size - input->pinyin_y) - 1;
char txt_buff[20] = {0};
WIN_PaintBackGround((WIN_WindowStruct *)input);
u32 font_type = WIN_SetFontSize(20);
// 显示文本
WIN_SetLcdColor(0x00ffff);
WIN_SetFontMode(WIN_DRAWMODE_ALONE);
WIN_DrawTxtAt(input->inputWords, x + 2, y + 2);
WIN_SetLcdColor(0xff0000);
WIN_DrawVLine(strlen(input->inputWords) * WIN_GetFontWidth() / 2 + x + 4, y,
y + 2 + WIN_GetFontHight());
WIN_SetLcdColor(0xffff00);
WIN_DrawRect(x, y, x_size, y_size);
// 显示键盘
WIN_SetFontSize(20);
for (int i = 0; i < 37; i++) {
if (input->button[i].press) {
WIN_SetLcdColor(0xbb00aa);
} else {
WIN_SetLcdColor(0xffffff);
}
WIN_FillRectByColor(input->button[i].x, input->button[i].y,
input->button[i].x_size, input->button[i].y_size);
WIN_SetLcdColor(0x000000);
WIN_DrawRect(input->button[i].x, input->button[i].y,
input->button[i].x_size, input->button[i].y_size);
WIN_DrawTxtHCenterAt(input->button[i].txt,
input->button[i].x + input->button[i].x_size / 2,
input->button[i].y + input->button[i].y_size / 2 -
WIN_GetFontHight() / 2);
}
// 显示拼音和候选字
if (input->inputMode == INPUT_MODE_PINYIN) {
WIN_SetFontSize(20);
if (input->inputPinyin[0]) {
WIN_SetLcdColor(0xaabbcc);
WIN_DrawTxtAt(input->inputPinyin, x, input->pinyin_y);
for (int i = 0; i < 10; i++) {
if (input->word[i].press) {
WIN_SetLcdColor(0xbb00aa);
} else {
WIN_SetLcdColor(0xffffff);
}
WIN_FillRectByColor(input->word[i].x, input->word[i].y,
input->word[i].x_size, input->word[i].y_size);
WIN_DrawRect(input->word[i].x, input->word[i].y, input->word[i].x_size,
input->word[i].y_size);
WIN_SetLcdColor(0x55bbaa);
WIN_DrawTxtHCenterAt(input->word[i].txt,
input->word[i].x + input->word[i].x_size / 2,
input->word[i].y + input->word[i].y_size / 2 -
WIN_GetFontHight() / 2);
}
}
}
WIN_SetFontSize(font_type);
}
// 默认消息处理函数
void INPUT_DefaultMsgLoop(WIN_InputStruct *input, WIN_MsgStruct *msg) {
WIN_MoveStruct *m = 0;
WIN_KeyStruct *k = 0;
switch (msg->msg) {
case WIN_MSG_PAINT:
INPUT_DefaultPaint(input);
break;
case WIN_MSG_KEY:
k = msg->data.p;
if (k->shortPress & KEY_VALUE_HOME) {
((WIN_WindowStruct *)input)->deleteWindow((WIN_WindowStruct *)input);
}
break;
case WIN_MSG_MOVE:
m = msg->data.p;
switch (m->moveType) {
case MOVE_DATA_TOUCHOUT:
INPUT_DoSomethingPressUp(input);
INPUT_SetPressUp(input);
WIN_SetInvalid((WIN_WindowStruct *)input);
if (input->exit)
((WIN_WindowStruct *)input)->deleteWindow((WIN_WindowStruct *)input);
break;
case MOVE_DATA_TOUCHIN:
input->press_x = m->x_move;
input->press_y = m->y_move;
INPUT_SetPressDown(input);
WIN_SetInvalid((WIN_WindowStruct *)input);
break;
default:
WIN_DefaultMsgLoop((WIN_WindowStruct *)input, msg);
break;
}
break;
default:
WIN_DefaultMsgLoop((WIN_WindowStruct *)input, msg);
break;
}
}
// 使用键盘输入一些数据
int INPUT_KeyBoard(WIN_WindowStruct *win, char *txt, int len) {
WIN_InputStruct *input = 0;
if (win)
input = WIN_CreatInput(win, 0, 0, 0, win->x_size, win->y_size);
else
input = WIN_CreatInput(0, 0, 0, 0, WIN_GetWinStruct()->lcd->getLcdSizeX(),
WIN_GetWinStruct()->lcd->getLcdSizeY());
int str_len = strlen(txt);
if (str_len < INPUT_WORDS_MAXNUM) {
mymemcpy(input->inputWords, txt, str_len + 1);
}
WIN_ShowWindow((WIN_WindowStruct *)input);
int ret = WIN_RunBlock((WIN_WindowStruct *)input);
WIN_GetBlockWinReturn(&ret, txt, len);
return ret;
}