本帖最后由 baiyongbin2009 于 2015-2-13 16:32 编辑 5 _ E. S5 G: Z" W! k% a- }
- B4 F( i# L: E特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接/ K4 r; Q; ~' M8 X4 R6 |% ?! @
第31章 键盘输入(实体按键操作控件) * d% O% o7 h$ B+ M
本期教程主要跟大家讲解键盘输入,这里我们通过开发板上面带的按键进行相关的操作,在后面会专门的做一期PS2键盘的教程。 31. 1 描述 31. 2 驱动层API 31. 3 实体按键操作 31. 4 总结 $ ~8 m% u5 I# [# U+ V3 e4 S
31.1 描述 键盘输入设备使用ASCII字符编码,以便区分不同的字符。例如,键盘上只有一个“A”键,但大写的“A”与小写的“a”拥有不同的ASCII编码 (分别为0x41和0x61) STemWin预定义字符编码 STemWin 同时定义了其他“虚拟”键盘操作的字符编码。这些编码如下表所示,由GUI.h中的标识符表中定义。因此,在emWin中,字符编码可以是任意扩展ASCII字符值,也可以是任意下列预定义的emWin值。 31.2 驱动层API 键盘驱动层处理键盘消息函数。这些程序会在具体键 (或组合键)被按下或松开时通知窗口管理器。 下表按字母顺序列出了驱动层键盘程序。详细描述 l 函数GUI_StoreKeyMsg() 把消息数据(Key, PressedCnt)存进键盘缓冲器,Key表示可以是任意扩展ASCII字符 (范围为0x20至0xFF)或者任意预定义的emWin字符编码。PressedCnt表示松开或者未按下的状态。 该函数可从中断服务程序调用。STemWin的键盘输入管理器含有一个FIFO缓冲器,默认情况下最多可以保存10个键盘事件。如果需要不同的尺寸,可以更改该值。 l 函数GUI_SendKeyMsg() 把键盘数据发送到输入焦点所在窗口。如果没有窗口有输入焦点,则调用GUI_StoreKeyMsg()函数将数据存储至输入缓冲器之中。该函数不可从中断服务程序调用。该函数的参数和上面函数的参数是一样的。 应用层的如下几个函数就先不做介绍了,使用到的时候再做介绍: 31.3 实体按键操作下面给大家讲解一下通过开发板上面带的按键来操作控件。按键的驱动请看安富莱STM32-V5开发板_用户手册的第20章:按键FIFO教程。此工程主 要分为两部分: Ø 按键任务 Ø STemWin主任务 按键任务: - /*' @& O0 l, U r, g8 i# {; ` x5 `
- *********************************************************************************************************
2 p6 r& l7 `5 c4 n( W) C p - * 函 数 名: AppTaskUserIF
7 N- v/ a( b2 a! S. Z - * 功能说明: 此函数主要用于得到按键的键值。
3 f# o1 K4 n7 w2 ~: m9 G4 E - * 形 参:p_arg 是在创建该任务时传递的形参' n* k- U' i" r
- * 返 回 值: 无
+ D! t9 ]. Y3 X6 j a - 优 先 级:23 [1 Y( n' T4 s. W. ?& r% [
- *********************************************************************************************************4 G3 W7 w& }. Q9 B
- */" h- I/ [0 a6 q) _) {& O) X& i
- static void AppTaskUserIF(void *p_arg)
/ q) o& i1 e7 x8 _' |1 R - {
9 j3 M" W% K* p) v" u0 i8 i" s, [ - uint8_t ucKeyCode;
) G) i* v7 e# e - % `1 \8 u9 O# l! {$ y
- (void)p_arg; /* 避免编译器报警 */2 v: a: a6 D5 L; ~6 ~
- 1 D- @& P5 Q2 A, M: t
- while (1) * E9 ~' l: `( V1 C
- { 9 h( r- s3 c/ H
- bsp_KeyScan();, Y! D5 E% V. A2 q" `/ Z
- ucKeyCode = bsp_GetKey();# r9 c0 e( e/ }- f
- if(ucKeyCode != KEY_NONE)
1 ~3 Z J, {* W B/ D7 k2 {- S - {
) c. T1 x5 i% d' N; Y - switch (ucKeyCode)
5 ~: B+ f! Q2 F- Q# J& H - {
) {. f( R4 v4 [( ~ - case KEY_DOWN_K1: /* K1键按下 实现截图*/ (1)
" d& g) ^/ \: F, C4 u, x - BSP_OS_SemPost(&SEM_SYNCH);
3 C$ M2 G- _. p0 n: F* r$ S - break;
; ~$ m+ T# c3 X: G- r -
( ~8 [, S2 M0 F5 S* p! G1 h* n - case KEY_DOWN_K2: /* K2键按下 实现TAB按键的功能*/ (2). G; @2 W y" k! f
- GUI_SendKeyMsg(GUI_KEY_TAB, 1);8 [6 a" u8 b0 W
- break;
& N+ e. H7 c( v* y! D* a - 1 [$ _! `5 D: D) I* ~& @) N" i9 M
- case KEY_DOWN_K3: /* K3键按下 实现CANCEL的功能 */ (3)
$ [$ S1 y8 y P% i' K - GUI_SendKeyMsg(GUI_KEY_ESCAPE, 1);+ a( M/ X% Q8 X3 ?
- break;
( t" x( e$ h9 X3 O- z R M - (4)
4 D2 ^; k: }, A3 G2 Z - case JOY_DOWN_U: /* 摇杆UP键按下 实现删除字符功能,注意和BACKSPACE回格的区别*/* S; l3 w# E& Y3 K f: F W) W
- GUI_SendKeyMsg(GUI_KEY_DELETE, 1);/ u J4 u/ v. a6 ~- G) S
- break;
5 V% u6 A& p- t/ x9 Q. Y -
& p3 w' v) ~% J. i. |, p - case JOY_DOWN_D: /* 摇杆DOWN键按下 实现删除字符 */ (5)# l) ^0 S! ~ [1 j! N
- GUI_SendKeyMsg(GUI_KEY_BACKSPACE, 1);
6 N- I, q: i; L: w - break;4 b6 P" z9 x4 n- a, k) B; _, B7 @
- M+ W4 r1 Q/ K6 H, U
- case JOY_DOWN_L: /* 摇杆LEFT键按下 实现光标左移 */ (6) Q1 M2 S b8 A
- GUI_SendKeyMsg(GUI_KEY_LEFT, 1);
0 p1 @# f: H. h% p! Z$ M! S [1 K - break;
4 B9 w5 U' [8 A5 C O -
9 U& d( S7 l+ |3 a. A - case JOY_DOWN_R: /* 摇杆RIGHT键按下 实现光标右移 */ (7)7 C, f; m# J: J. z
- GUI_SendKeyMsg(GUI_KEY_RIGHT, 1);
9 L$ e; Y9 `) L4 c - break;! ?4 H& p' D7 y! G% n" J1 C+ d
- . E, [" @3 `4 D
- case JOY_DOWN_OK: /* 摇杆OK键按下 实现OK */ (8)/ U* Y1 u+ O0 }' L
- GUI_SendKeyMsg(GUI_KEY_ENTER, 1);6 R- J4 n3 ~- [6 I2 h7 K
- break;6 T ^+ O P5 e: F' j4 F% B: g
-
' |0 a2 k/ @9 T3 {/ ^7 _) N - default:# i4 y! ]+ a" }( U. B4 C( {
- /* 其它的键值不处理 */8 [6 N- @' E2 _" S' {- e& E
- break;+ y' [% w. E$ o |. i1 B) H9 R' f
- }( |9 |' X1 W# Y9 l+ L' P# ^# n2 A
- }* x/ t3 J4 h- J. ~1 L+ w
- BSP_OS_TimeDlyMs(10);) p1 {1 j* T( ]/ L7 w
- }' h% s. u6 v1 @( Q) x
- }
复制代码1. 按下按键1实现截图功能。 2. 实现TAB按键的功能。 3. 实现CANCEL的功能 4. 实现删除字符的功能,注意和BACKSPACE回个的区别。 5. 实现删除字符 6. 实现光标左移。 7. 实现光标右移。 8. 实现OK键功能。 STemWin主任务: - #include "includes.h"4 u! Z( t1 U3 j3 [( A! L- \
- #include "MainTask.h"6 f0 q3 u3 r( W3 t7 M& L8 {! p6 d" A
- " B1 |+ m# L3 X3 f/ Z
-
: l+ O4 M4 I4 q, f4 T) O; K! G - /*
, \1 ^1 Y0 c. E; s, B9 J - ********************************************************************************************************' h5 ?% Z, O3 \4 W! o
- * 静态数据# p8 U! C. R$ W' f3 Y; }
- ********************************************************************************************************
9 g9 J# J$ I& N9 I; i$ n - */
" X# j# P% e3 d7 B - static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = 7 b* E! G( f% D9 m: Y+ l1 n! t
- {
/ A1 A5 {$ r- {; e - { FRAMEWIN_CreateIndirect, "Edit winmode", 0, 90, 90, 140, 130, FRAMEWIN_CF_MOVEABLE},
; L( Q. a: ~5 \ - { EDIT_CreateIndirect, NULL, GUI_ID_EDIT0, 10, 10, 110, 20, 0, 15},
* v% I0 Y! m! A8 i' W* d - { EDIT_CreateIndirect, NULL, GUI_ID_EDIT1, 10, 40, 110, 20, 0, 15},
6 b* h9 D" `/ @4 w& n - { BUTTON_CreateIndirect, "Ok", GUI_ID_OK, 10, 80, 50, 20 },. M: t3 a9 Y- W+ E/ ?. ]# }
- { BUTTON_CreateIndirect, "Cancel", GUI_ID_CANCEL, 70, 80, 50, 20 },$ ` v/ c7 }6 d4 O) p# M \/ [
- };
' P' a' V, z* O8 } ^/ ?$ A1 M - . l7 C, o7 X# B( L/ n
- static char * _apExplain[] =
5 [' Z X2 I8 C - {! {. O8 f1 U, y! x" {* N/ _
- "This sample shows how to use edit widgets with a",6 F3 e" v; I& d* B. D: a5 l, s
- "user defined callback function and how to set a",6 e0 j5 M6 z1 ^! o* F6 ?& B
- "user defined AddKey function. It selects the",! }9 k' Z: B6 N6 _4 P8 a0 \$ x$ g
- "contents of the edit field on receiving the focus",
- _* d! k/ o& x) X - "and overwrites the contents if a key other than",1 s& K$ C2 A6 z! ?5 ^) ?# H8 h& |
- "a cursor key is pressed.",7 v G0 P6 j( Q- X% z
- };
o& m; S$ Z6 K -
- b, p4 H& E [6 O' F - /*
, D% m P$ Q$ N# ? - *********************************************************************************************************
9 J9 \% V' p/ s - * 函 数 名: _cbDialog0 q2 X1 y& V; a$ S3 c$ s
- * 功能说明: 对话框的回调函数. G6 z( b. L: Q
- * 形 参:pMsg 消息指针
( C1 f% X+ P8 r3 R& y - * 返 回 值: 无! s# A4 |) }$ |; O( I: {
- *********************************************************************************************************
: C* v7 \9 G8 Y- t# o - */
. A; c. E1 r) n; r, V2 q' W - static void _cbDialog(WM_MESSAGE * pMsg) 6 G v# C% e+ A2 _ ^
- {
2 `* [7 D9 c1 M0 p - int i;
1 J m4 K8 K$ I8 N3 p - int NCode;3 H! d5 q! C2 m
- int Id;
+ S' ?$ a! t" A/ \; s: W* Y - WM_HWIN hDlg;2 p' z9 B0 T( q
- WM_HWIN hItem;0 Z& Q6 {5 Y9 e# e: r
-
7 h* Y& f- j9 z& o! E. ^3 |& m - hDlg = pMsg->hWin;
9 ] ? M3 ~# n% Y' [ - switch (pMsg->MsgId) 5 m# N+ N4 w0 W
- {
" S8 `" j9 V8 |8 X5 p - case WM_INIT_DIALOG:) o0 A4 f: u" K, E0 H
- FRAMEWIN_SetFont(pMsg->hWin, &GUI_Font13_ASCII);
% p% V; _; Y# R0 K& n4 g9 c - FRAMEWIN_SetTextAlign(pMsg->hWin, GUI_TA_HCENTER);
0 ]( m* R' Y! ~8 H) V" Q - for (i = 0; i < 2; i++) ! ^ \+ x- y1 H
- {8 Q+ E# Y' V8 M+ Z
- hItem = WM_GetDialogItem(hDlg, GUI_ID_EDIT0 + i); // Get the handle of the edit widget1 U$ e1 z1 l( y' Y9 g3 ^* v$ H
- }
: z# f0 G; w ?' P2 { - break;& [; p; A: H( n q; i
- case WM_KEY:0 H. Z3 t7 z& J! }5 z( A
- switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key)
2 U b) y0 W* a- v2 _, K - {
: o B7 P3 i- f - case GUI_KEY_ESCAPE:
5 G" d/ b; }: c6 A# T - GUI_EndDialog(hDlg, 1);
& U. X8 h- p7 U. x" x - break;
3 O* D1 q6 v5 s z9 x - case GUI_KEY_ENTER:- W2 {3 V. J2 o6 B& _
- GUI_EndDialog(hDlg, 0);
% }) g& ]) C! P6 U - break;! \" P; P" }! T% A1 d
- }
8 R; ~& K+ [- d4 b' ~ - break;4 s! |) e! B5 C# s
- case WM_NOTIFY_PARENT:2 K6 O) S' c5 \% _. ^" b: \
- Id = WM_GetId(pMsg->hWinSrc); // Id of widget
. I# Z. e) h% e0 A- f - NCode = pMsg->Data.v; // Notification code; l- d3 K* X# Y% c. m, v0 J
- switch (NCode) # t ~4 q2 S: Q8 _: t" P; w7 G
- {
' u% j% [5 f8 N. D6 @ - case WM_NOTIFICATION_RELEASED: // React only if released
8 |6 H; D" S% K* M# u - if (Id == GUI_ID_OK)
) [! I8 X1 Y% P3 r | - { // OK Button
: X1 _& c" A! }8 a - GUI_EndDialog(hDlg, 0);. m( c$ i6 ^5 P; Z/ t
- }
O% \; @, ^+ \% n! Y* z4 u - if (Id == GUI_ID_CANCEL)
! N: r9 o; U8 ~: Y% j - { // Cancel Button
( Z. G) V6 K4 ~0 r4 q - GUI_EndDialog(hDlg, 1);) K: c& f3 j, D$ L
- }
& |- {+ X9 @/ _9 j, v0 R - break;, y, S+ c2 Y2 o3 ?: z8 u
- }7 L1 g6 u& [6 Y* y6 ?6 ~- C7 _ c
- break;
1 a+ a: @3 P; s Y! s - default:8 K \# G& P2 }6 E
- WM_DefaultProc(pMsg);
/ D" _; }# {& e3 D) } - }+ `- ?6 h0 @" z7 f3 W: }. U$ }: \+ V
- }
, a# w5 a/ F' l - ( j* k/ N! ?* ?5 ]$ p {' d) D
- /*
/ O% f# s- w: U. [ - *********************************************************************************************************; C7 D7 V! H+ k1 n- Y2 j
- * 函 数 名: _cbDesktop
: g6 G0 G1 d. g/ N/ l7 n - * 功能说明: 桌面窗口的回调函数& n( y4 b9 {' W
- * 形 参:pMsg 消息指针
% ^) o2 g4 q. {1 z. Q; a; I0 j - * 返 回 值: 无
3 s# z1 Z* A; ~! K( y; K - *********************************************************************************************************
5 V, \. Q! \( W8 {% n4 J - */( x( x; I6 X5 @* Q+ F% Y
- static void _cbDesktop(WM_MESSAGE * pMsg) : O4 C$ q- @9 o0 Y0 e, G- k b
- {$ \9 {5 o* w/ C( x p
- unsigned i;7 l! i5 ^1 ]3 j/ [
- - k' e, s( p, P0 K6 n) X
- switch (pMsg->MsgId)
9 W8 Q/ j3 y6 J( E/ y U - {
1 k/ i) }- W4 q9 L7 l - /* 重绘 */
1 ^% N7 J, p& I2 {. s - case WM_PAINT:
/ p1 u( R+ v4 a - GUI_SetBkColor(GUI_RED);
, ]. Q& O. H: I) ^9 n; { - GUI_Clear();
5 E3 G& r# q7 p- V( u7 u - GUI_SetFont(&GUI_Font24_ASCII);
& E8 J# p# ^# o$ u6 H$ X) L - GUI_DispStringHCenterAt("WIDGET_EditWinmode", 160, 5);4 X# G7 _+ p$ T4 ]: u
- GUI_DispNextLine();/ o( e7 A K4 g R
- GUI_SetFont(GUI_DEFAULT_FONT);1 h' s% p7 l8 U8 @- M
- GUI_DispNextLine();
7 n. a4 U E5 z - for (i = 0; i < GUI_COUNTOF(_apExplain); i++) # y4 L0 K; w/ w
- {' z. j; J; C( l/ A8 c" j
- GUI_DispStringHCenterAt(_apExplain[i], 160, GUI_GetDispPosY());# B* c2 N/ T. p8 d9 V
- GUI_DispNextLine();2 ]) s2 f U' H( V
- }8 C2 S8 }& P2 e2 ~/ P
- break;
+ ]# E3 @' N* P$ o6 [ - }, c2 ^; y6 R9 s: a) ^
- }, ~3 M: s* B v' s' ~! |( L2 ]0 M+ d
- 1 Q. Y$ g+ Q0 o$ n3 m: Z
- /*$ y- W2 j- m- Z) h- |
- *********************************************************************************************************/ x. E+ D5 v% X; |+ ~
- * 函 数 名: MainTask
1 C# v, ~7 C. c# M" q4 I9 T - * 功能说明: GUI主函数
: K; q0 T) A; |2 Z. G& ^ - * 形 参:无
6 ]; y" {* f# `0 u, m - * 返 回 值: 无
5 P# H1 \9 N* B8 u# H" w9 w - *********************************************************************************************************; |0 {; h, F: z) _; ?+ N4 l0 c
- */
* b3 G; x) H# \0 n( v - void MainTask(void) ! [% _/ R8 [# K! m3 ?2 G5 {+ L5 s
- {, j" {# P3 u9 f
- GUI_Init();) M" K$ T( j( j/ I+ _- z6 j9 C% u+ ? y
- WM_SetCallback(WM_HBKWIN, _cbDesktop);
! y# L* M5 F2 [; V1 U) q7 Q - while(1) ! v0 H* l, y$ [$ \4 U: `
- {
' {9 ]$ V& A- R- P& P5 t6 g% u - /* 创建阻塞式对话框 */0 u9 h- C: ^: s* \9 H
- GUI_ExecDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbDialog, 0, 0, 0);8 t/ @+ `7 x' B( I/ Q% [
- GUI_Delay(1000);
& H3 C" ?, ?4 ]7 Q - }. p2 I0 z- [, c1 p
- }
复制代码1. 上面的程序比较简单,主要是在对话框上面显示一个编辑框(初学的不要担心,后面教程会有这些控件的讲解)。 2. K1按键实现的是TAB键的功能,主要是实现对话框上面控件的聚焦切换。 其余的按键功能比较简单,实际操作下就明白了,上面的代码中也有相应的注释。 尝试了一下自定义按键消息没有成功,后面再试试。 3. 按键具体的通讯机制会在后面的教程中再跟大家讲解。 实际的显示效果如下: 31.4 总结 本期教程就跟大家讲这么多,主要是想通过本期教程让大家对实体按键操作控件有一个了解。这个过程还需要大家对通信机制有所了解。在后面的教程中会跟大家详细讲解通信机制这块。 , m0 N# S- S8 E7 \5 I
|