你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【安富莱STemWin教程】第31章 键盘输入(实体按键操作控件)

[复制链接]
baiyongbin2009 发布时间:2015-2-13 16:31
本帖最后由 baiyongbin2009 于 2015-2-13 16:32 编辑
* z1 W& m/ d  H
! g& c# M, w1 ]0 |; s特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接: J  \$ W* M% |% X5 K8 @3 K
第31章 键盘输入(实体按键操作控件)

5 i* y8 B3 }9 Q& H1 \
    本期教程主要跟大家讲解键盘输入,这里我们通过开发板上面带的按键进行相关的操作,在后面会专门的做一期PS2键盘的教程。
    31. 1  描述
    31. 2 驱动层API
    31. 3 实体按键操作
    31. 4 总结

' Z: a, y+ _/ k% m9 L/ M31.1 描述
    键盘输入设备使用ASCII字符编码,以便区分不同的字符。例如,键盘上只有一个“A”键,但大写的“A”与小写的“a”拥有不同的ASCII编码 (分别为0x41和0x61)
STemWin预定义字符编码
    STemWin 同时定义了其他“虚拟”键盘操作的字符编码。这些编码如下表所示,由GUI.h中的标识符表中定义。因此,在emWin中,字符编码可以是任意扩展ASCII字符值,也可以是任意下列预定义的emWin值。
预定义的虚拟键盘码
描述
GUI_KEY_BACKSPACE
退格键
GUI_KEY_TAB
制表键
GUI_KEY_ENTER
回车键
GUI_KEY_LEFT
左箭头键
GUI_KEY_UP
上箭头键
GUI_KEY_RIGHT
右箭头键
GUI_KEY_DOWN
下箭头键
GUI_KEY_HOME
本位键(移至当前行的开头)
GUI_KEY_END
结束键(移至当前行的末尾)
GUI_KEY_SHIFT
换挡键
GUI_KEY_CONTROL
控制键
GUI_KEY_ESCAPE
换码键
GUI_KEY_INSERT
插入键
GUI_KEY_DELETE
删除键
31.2 驱动层API
   键盘驱动层处理键盘消息函数。这些程序会在具体键 (或组合键)被按下或松开时通知窗口管理器。
下表按字母顺序列出了驱动层键盘程序。详细描述
程序
描述
GUI_StoreKeyMsg()
把消息存储于指定键
GUI_SendKeyMsg()
把消息发送至指定键。
l 函数GUI_StoreKeyMsg()
    把消息数据(Key, PressedCnt)存进键盘缓冲器,Key表示可以是任意扩展ASCII字符 (范围为0x20至0xFF)或者任意预定义的emWin字符编码。PressedCnt表示松开或者未按下的状态。
    该函数可从中断服务程序调用。STemWin的键盘输入管理器含有一个FIFO缓冲器,默认情况下最多可以保存10个键盘事件。如果需要不同的尺寸,可以更改该值。
l 函数GUI_SendKeyMsg()
    把键盘数据发送到输入焦点所在窗口。如果没有窗口有输入焦点,则调用GUI_StoreKeyMsg()函数将数据存储至输入缓冲器之中。该函数不可从中断服务程序调用。该函数的参数和上面函数的参数是一样的。
    应用层的如下几个函数就先不做介绍了,使用到的时候再做介绍:
31.1.png
31.3 实体按键操作
下面给大家讲解一下通过开发板上面带的按键来操作控件。按键的驱动请看安富莱STM32-V5开发板_用户手册的第20章:按键FIFO教程。此工程主 要分为两部分:
  Ø 按键任务
  Ø STemWin主任务
按键任务:
  1. /*, z) ]% L. ^, m+ Z
  2. *********************************************************************************************************& Q+ f8 ]" ]5 Q. |. m2 g& \
  3. *        函 数 名: AppTaskUserIF
    & F4 Q* U1 O, }) @% @8 v
  4. *        功能说明: 此函数主要用于得到按键的键值。  a$ o8 u3 ^! y6 s% B
  5. *        形    参:p_arg 是在创建该任务时传递的形参2 I( B+ [& x7 D
  6. *        返 回 值: 无
    ' M, M1 i' n! f: B7 `
  7. 优 先 级:2# i( p/ |1 ?6 i3 N
  8. *********************************************************************************************************8 B: P+ R! ^& @& N; B% m
  9. */
    + L1 g& W7 u. f! E; o0 r
  10. static void AppTaskUserIF(void *p_arg)
    , V6 [0 {& L8 n
  11. {9 V( n* ?& p3 l2 \% x' p
  12. uint8_t ucKeyCode;* L# R# r+ ^5 d1 N( f
  13. 9 ?* d3 c# V1 I& J
  14. (void)p_arg;                       /* 避免编译器报警 */
    & b& R9 z' k. w9 g1 M
  15. ! F6 _9 }9 ~. O3 c
  16. while (1) . \* R0 f& e& a3 v
  17. {   & @2 l2 k! ]8 v1 [/ s* u
  18. bsp_KeyScan();
    & b: |3 I& I/ `
  19. ucKeyCode = bsp_GetKey();* W$ K; U/ l! `( O  d
  20. if(ucKeyCode != KEY_NONE)8 |( c+ E0 ?( H% `
  21. {
    4 _" P( ~( v/ Z( `! [/ e( Z
  22. switch (ucKeyCode)
    9 [6 x# T: y; e% C
  23. {
    $ R4 E  ^: }/ D1 L
  24. case KEY_DOWN_K1:         /* K1键按下 实现截图*/                                (1)
    / H2 F3 j6 i2 }( ~+ t  F$ }3 D
  25. BSP_OS_SemPost(&SEM_SYNCH);
    : M* ]7 `' ^1 J" G0 R* u* P
  26. break;
    ( A* i% O" Q0 `% F) N
  27. 9 q9 C/ {: `# M: P8 O9 j0 P
  28. case KEY_DOWN_K2:         /* K2键按下 实现TAB按键的功能*/                      (2)( t$ Q% M3 I5 }. q
  29. GUI_SendKeyMsg(GUI_KEY_TAB, 1);
    ' O& q* M  i4 c% K6 U9 F
  30. break;
    4 z5 R: r1 L7 z& G% k

  31.   F# W- G4 {7 o# _* R, O5 e& E
  32. case KEY_DOWN_K3:         /* K3键按下 实现CANCEL的功能 */                      (3)
    $ M* ]2 \% H- m* ]& Y
  33. GUI_SendKeyMsg(GUI_KEY_ESCAPE, 1);/ w4 i' m+ u, t
  34. break;4 y9 Q2 n  t4 }5 e/ m
  35. (4)# U* n$ A, l. N/ D8 l
  36. case JOY_DOWN_U:         /* 摇杆UP键按下 实现删除字符功能,注意和BACKSPACE回格的区别*/
    - [2 t2 y8 _# `6 _- n: \% o4 `2 C
  37. GUI_SendKeyMsg(GUI_KEY_DELETE, 1);3 b- Y$ i0 b8 {  V- F7 Q6 ^* p
  38. break;
    % M9 F. R# w- d0 o& X+ S  {
  39. ; Y+ I6 b  f; d7 C& f5 H
  40. case JOY_DOWN_D:         /* 摇杆DOWN键按下 实现删除字符 */                    (5)& {) ]& b) h% G. _; s) R9 x/ h
  41. GUI_SendKeyMsg(GUI_KEY_BACKSPACE, 1);
    ! k& w3 f0 i! l; L8 a4 Z) l
  42. break;
    % g8 v4 t+ p1 H; B- `3 S' ~9 D

  43. 2 N) E- m; g. n
  44. case JOY_DOWN_L:         /* 摇杆LEFT键按下 实现光标左移 */                    (6)
    : V( n" b& a- e' E
  45. GUI_SendKeyMsg(GUI_KEY_LEFT, 1);
    , k5 J/ U! h" j% o5 X
  46. break;
    + g3 x# A! ?6 \& g
  47. 3 x5 Q* ]* w5 c7 V/ z
  48. case JOY_DOWN_R:         /* 摇杆RIGHT键按下 实现光标右移 */                   (7)
    6 L$ X' l- Z1 t$ [5 a
  49. GUI_SendKeyMsg(GUI_KEY_RIGHT, 1);2 `1 x# k% s0 j! o/ F% |% ~
  50. break;
    3 X9 f9 Y# L4 a# J" u/ h

  51. 9 t# T  Q- S, ]: `
  52. case JOY_DOWN_OK:         /* 摇杆OK键按下 实现OK */                           (8)! a" D* K; P( Z9 [) q; p0 \% u
  53. GUI_SendKeyMsg(GUI_KEY_ENTER, 1);
    5 E( u' }; w0 k" o# `* y/ {
  54. break;3 ~2 X2 w! }3 ?  x
  55. ; q! b, N# ~+ g8 p9 d
  56. default:
    * P+ [. l$ u: Y8 M
  57. /* 其它的键值不处理 */
    / o( p! \7 ~3 ]6 \# F$ E% D9 D
  58. break;. c2 q2 p! R1 y7 g1 k5 S
  59. }) M, Y. I( \9 d
  60. }# f5 I+ R  N0 N2 e; `
  61.         BSP_OS_TimeDlyMs(10);
      w1 N& X# _9 M9 z( @
  62. }1 a5 r5 z; h' V& \! e
  63. }
复制代码
1. 按下按键1实现截图功能。
2. 实现TAB按键的功能。
3. 实现CANCEL的功能
4. 实现删除字符的功能,注意和BACKSPACE回个的区别。
5. 实现删除字符
6. 实现光标左移。
7. 实现光标右移。
8. 实现OK键功能。
STemWin主任务:
  1. #include "includes.h"
    ! u3 ^2 `/ w: S* }( p. C" F5 u
  2. #include "MainTask.h"
    7 x, V2 Q; @" t& Q

  3. ( D& h5 u1 }: B+ y) [
  4. % u9 a! z: E' L7 ~& T
  5. /*- w- b) v5 K8 L" Z  R4 n8 V, F
  6. ********************************************************************************************************7 q3 J3 X# f4 i4 Q( {
  7. *                             静态数据
    ! Z; P" m9 |9 e' n4 F7 F
  8. ********************************************************************************************************1 U* M; K, ?$ ^! {, U2 B# ?; ^
  9. */4 R7 P5 ?4 D( O; u, t0 t# k
  10. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = ' H/ ~6 v3 R; x# I7 f, X
  11. {
    : {6 p4 I  G: Z7 q1 c* w/ R$ u, f' [
  12. { FRAMEWIN_CreateIndirect, "Edit winmode", 0,         90,  90, 140, 130, FRAMEWIN_CF_MOVEABLE},
    8 O- q2 L* s5 H
  13. { EDIT_CreateIndirect,     NULL,     GUI_ID_EDIT0,    10,  10, 110,  20, 0, 15},
    " j4 J$ a4 E5 s: @
  14. { EDIT_CreateIndirect,     NULL,     GUI_ID_EDIT1,    10,  40, 110,  20, 0, 15},& {- w( x" U8 [  M! q# ]) }
  15. { BUTTON_CreateIndirect,   "Ok",     GUI_ID_OK,       10,  80,  50,  20 },4 U/ y) r; P( m) }+ [* I2 d* R9 p- H5 J
  16. { BUTTON_CreateIndirect,   "Cancel", GUI_ID_CANCEL,   70,  80,  50,  20 },) d+ X. |4 `1 {( y- k9 J
  17. };
    6 ?& K- A$ y/ ^  }
  18. 3 J: b7 l  e. ^3 s
  19. static char * _apExplain[] = * [9 s. w$ Y; I& J7 V/ x
  20. {  H, C5 }. O3 l$ l
  21. "This sample shows how to use edit widgets with a",$ [+ j) l: R& |
  22. "user defined callback function and how to set a",6 g6 I7 L' @! o" D+ J. Q8 t
  23. "user defined AddKey function. It selects the",+ }( C+ ~' _# [( E. n% L
  24. "contents of the edit field on receiving the focus",
    " R3 F" w$ c2 B6 {' [- L! z
  25. "and overwrites the contents if a key other than",
    ! n0 T; m& m. O' f  [
  26. "a cursor key is pressed.",' }8 m1 t1 R0 p6 U0 w
  27. };5 W2 j& ?2 j. k6 H0 V

  28. ! V9 o% b. `" {# z+ L$ X6 I5 l
  29. /*8 x' q( }; m% [/ t- Y" g3 k0 l
  30. *********************************************************************************************************6 b8 Q0 M' k: T$ y5 X" C  L
  31. *        函 数 名: _cbDialog2 `; K& H8 P3 n" h/ d! m
  32. *        功能说明: 对话框的回调函数" [9 z% M. J$ w; [7 m
  33. *        形    参:pMsg 消息指针- R% ]1 V/ f- G
  34. *        返 回 值: 无
    4 \$ Q# L' u# w1 A6 A0 S, ^' v
  35. *********************************************************************************************************
    ) b! a8 Q4 X) w- b
  36. */
    ( C- n' Q9 `9 z8 x3 U
  37. static void _cbDialog(WM_MESSAGE * pMsg) - w# ]3 r! |, ]  S3 J
  38. {
    / K  k. m* P4 {$ F% _5 `
  39. int     i;
    # ^. A! p7 B% J+ ?
  40. int     NCode;
    ' E' P% J9 i8 H6 B# h
  41. int     Id;
    5 l: e9 S, V5 C9 N1 N' R
  42. WM_HWIN hDlg;& k! a* Z# ^: }: Y! A5 V3 N. S: p
  43. WM_HWIN hItem;& h+ }$ e1 d: f' ~6 Y: X

  44. 2 i0 R7 E$ Y* W1 _  m0 o
  45. hDlg = pMsg->hWin;
    & m( o) z. d3 h' A) f
  46. switch (pMsg->MsgId) 3 i0 t1 Z% h0 {0 I9 t' A
  47. {
    2 {* n( l" C! w8 a3 v
  48. case WM_INIT_DIALOG:
    5 e  p) \( g' w- h, B
  49. FRAMEWIN_SetFont(pMsg->hWin, &GUI_Font13_ASCII);
    % G; a1 W1 C/ I8 _' Z0 k) J& `
  50. FRAMEWIN_SetTextAlign(pMsg->hWin, GUI_TA_HCENTER);
    ; ^0 c3 |1 z* o8 S+ h3 {; `- ]: R0 R1 _
  51. for (i = 0; i < 2; i++)
    1 i( {2 K" R% j0 O9 I- a& S
  52. {8 S/ S/ j5 O, |
  53. hItem = WM_GetDialogItem(hDlg, GUI_ID_EDIT0 + i);  // Get the handle of the edit widget
    ) w. m# i) [+ H: F4 I8 T6 O1 l
  54. }: U7 w2 B; s1 ?8 X6 V
  55. break;
    : W& \3 b  q0 J; |
  56. case WM_KEY:- P, s+ E# B4 W& J# z
  57.             switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key)
    7 @! b+ M- R& z- x
  58.             { 0 Y! q/ d$ v$ E/ H( `- f" @
  59. case GUI_KEY_ESCAPE:4 B, D* |4 T- p: Y) z' k
  60.                     GUI_EndDialog(hDlg, 1);
    2 W% @  l: N, T3 w" W- v! V
  61.                     break;9 }6 ^- X" m$ Y! d- {8 O
  62.                 case GUI_KEY_ENTER:
    " S! }2 s% {& u) X- J
  63.                     GUI_EndDialog(hDlg, 0);8 B; a9 u* M  A: p" J
  64.                     break;
    & P# p! ]' N& Q+ n
  65.             }- e1 W! ^/ z% P8 H2 B. s* D0 y1 j; V
  66.             break;
    1 l) L+ e( B" I2 `  C) p
  67. case WM_NOTIFY_PARENT:$ v/ p! p5 h$ h8 R
  68. Id    = WM_GetId(pMsg->hWinSrc);      // Id of widget
    # K0 f; L; [  w5 v0 K* _6 }7 }
  69. NCode = pMsg->Data.v;                 // Notification code
    ; J# v5 D* B, M1 Y
  70. switch (NCode)
    0 I- H0 [; R  k( q- M3 x
  71. {
    - I4 e! O" n3 V( _- l1 [* l2 K- _
  72. case WM_NOTIFICATION_RELEASED:      // React only if released$ h  s1 u$ f: M6 r& a6 _
  73. if (Id == GUI_ID_OK)
    * R# O1 c/ J8 V% R1 T
  74. {         // OK Button
    1 T9 y, W9 _/ f. R( j6 t$ ?# W) h4 O
  75. GUI_EndDialog(hDlg, 0);
    ( c& c8 V( R% ~6 r7 r$ h/ R( r, O
  76. }+ @, P& D% _! K; \' d
  77. if (Id == GUI_ID_CANCEL)
    ( r# H' p' B& [; m' F; p( M' S
  78. {        // Cancel Button
    * ?4 ]9 ?* B* }* T& g& h! \2 R
  79. GUI_EndDialog(hDlg, 1);
    ' s1 e% \: t, e6 b$ I9 i5 H$ Q
  80. }
    % b5 A, W) R* o5 z+ x4 J
  81. break;0 g5 y( p! K6 p) `5 i
  82. }
    ) P6 G/ k) H7 G9 s3 s! D
  83. break;- n  R9 x1 r7 k  O& r; p" ?
  84. default:6 ]0 h. O$ m- A7 f$ M4 p
  85. WM_DefaultProc(pMsg);
    6 f( _( X/ _! M) h8 E
  86. }2 v( D# E& d8 }' q1 q# J) [+ M( {
  87. }. w* G: J" }8 ]2 l) ]
  88. 0 X. F2 [# U, m" `
  89. /*: K/ m, i: m: n2 @' W: x! H( C
  90. *********************************************************************************************************- H) f* q& c# v) ~2 E8 C# U
  91. *        函 数 名: _cbDesktop+ s( b, ^: z. ^5 U
  92. *        功能说明: 桌面窗口的回调函数7 g: k8 n* {! V. c- k6 k3 J
  93. *        形    参:pMsg 消息指针
    ( e6 ?% b$ \, N4 Q
  94. *        返 回 值: 无8 N3 ?8 }+ |' w2 r' Z7 W5 [3 L# r: o- [
  95. *********************************************************************************************************
    6 c+ b! h; k: I+ q+ _" q# s
  96. */
    + z- B- a" x/ e6 l2 K
  97. static void _cbDesktop(WM_MESSAGE * pMsg)
    / X8 h, v, J* q2 `
  98. {
    : @) S) L6 ^# O. _0 D3 K; v, {  b
  99. unsigned i;4 n  ^; z7 L7 D, N
  100. 3 d: V  c2 e) T; N
  101. switch (pMsg->MsgId)
    8 [! s0 z# t6 I. N
  102. {
    , J3 c$ {. f$ j0 `, \( B
  103. /* 重绘 */
    . A3 l+ v0 {; u' m
  104. case WM_PAINT:# k- T5 K; \$ @
  105. GUI_SetBkColor(GUI_RED);1 @; s: s1 e' n
  106. GUI_Clear();( v* g& K+ ^9 l2 j
  107. GUI_SetFont(&GUI_Font24_ASCII);  f6 B6 k4 _, C) B6 t7 o
  108. GUI_DispStringHCenterAt("WIDGET_EditWinmode", 160, 5);$ r+ }3 R3 G$ R- g, P$ P4 n
  109. GUI_DispNextLine();
    ! ~7 V4 i% @3 ]  I
  110. GUI_SetFont(GUI_DEFAULT_FONT);
    ; q( q/ ~$ H' K, J
  111. GUI_DispNextLine();
    % J& R$ H1 F8 j8 }1 o( g
  112. for (i = 0; i < GUI_COUNTOF(_apExplain); i++)
    6 F& v# o  J6 `
  113. {/ p& c2 \9 e7 X/ w5 U4 }+ V8 C
  114. GUI_DispStringHCenterAt(_apExplain[i], 160, GUI_GetDispPosY());
    4 {( O( B- ~2 r" H" Y& B
  115. GUI_DispNextLine();
    0 Q) i$ U- D4 a. s
  116. }* I: s, q' L7 K0 R
  117. break;/ [# K! a, s2 ~" p1 [
  118. }- d- @5 u2 _! x* l, Q$ f
  119. }# Z8 h8 c. U: _% `  I8 y( n
  120. 0 E- S8 [- O9 Q& X1 p
  121. /*. M/ w; I) p* V
  122. *********************************************************************************************************
    4 w3 q' F) e) Z, c2 Y# ^
  123. *        函 数 名: MainTask
    4 v2 ]/ S3 S+ m: V. V* _( x; }
  124. *        功能说明: GUI主函数
    - \+ n# N. [" G4 ^' b3 C3 Q. f: O
  125. *        形    参:无% a9 n' m0 W% p% r1 x
  126. *        返 回 值: 无& J8 Q+ F4 j; j
  127. *********************************************************************************************************. q8 v' v5 A/ |3 [4 R! K2 H
  128. */1 f$ E& }; W4 W2 i1 U1 ?
  129. void MainTask(void) 2 H. e4 b" C2 ?$ b( _1 v5 z4 r2 ?
  130. {. W" J' o/ G$ @# r& `0 P9 E  M4 l
  131. GUI_Init();
    # P0 Q6 x' U3 R
  132. WM_SetCallback(WM_HBKWIN, _cbDesktop);4 y: P7 c: p* U7 L
  133. while(1) 4 ~& X. H. M) L6 f" i
  134. {
    ! G: f. f/ x/ U: X* v# Q  ]
  135. /* 创建阻塞式对话框 */
    5 @/ D& o7 m: `1 f5 \6 ^6 n
  136. GUI_ExecDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbDialog, 0, 0, 0);
    " l- P3 O( R* b5 G
  137. GUI_Delay(1000);
    ( t9 k8 ^" P# H: F  l; ?" N  d
  138. }
    / |1 ^# a6 w4 ]
  139. }
复制代码
1. 上面的程序比较简单,主要是在对话框上面显示一个编辑框(初学的不要担心,后面教程会有这些控件的讲解)。
2. K1按键实现的是TAB键的功能,主要是实现对话框上面控件的聚焦切换。
    其余的按键功能比较简单,实际操作下就明白了,上面的代码中也有相应的注释。
    尝试了一下自定义按键消息没有成功,后面再试试。
3. 按键具体的通讯机制会在后面的教程中再跟大家讲解。
实际的显示效果如下:
31.2.png
31.4 总结
    本期教程就跟大家讲这么多,主要是想通过本期教程让大家对实体按键操作控件有一个了解。这个过程还需要大家对通信机制有所了解。在后面的教程中会跟大家详细讲解通信机制这块。
* r+ Y5 T' ?9 o; u$ Z/ A3 s4 p+ L
赞 收藏 评论1 发布时间:2015-2-13 16:31

举报

1个回答
lkl0305 回答时间:2015-2-13 23:31:04
多谢分享,学习下
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版