When a BUTTON is continually pressed, I want a variable to continuously increment.

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • When a BUTTON is continually pressed, I want a variable to continuously increment.

      Hello!

      Can anyone show me how to use the callback of a BUTTON to continuously increment a variable when the BUTTON is continually pressed?
      Description:
      1) I created a button (that works well)
      2) It changes bitmap based on WM_NOTIFICATION_CLICKED and WM_NOTIFICATION_RELEASED (that works well)
      3) Initially I wanted my variable (Count) to increment upon: WM_NOTIFICATION_RELEASED (that works)
      case WM_NOTIFICATION_RELEASED:
      Count++;
      4) Now I need to have Count continuously increment as long as BUTTON is kept in the PRESSED state. Just like a normal keyboard: aaaaaaaaaaaaaaaaaaaaaaaaaaa

      Can you show me how to do that please?

      Thanks
      E4M
    • Hi,

      You can use a timer which gets started on button click. On the WM_TIMER message simply check if the button is still pressed. If it is restart the timer, maybe with a lower period, and increment a value.

      Below is a short example. The variable "TimerInc" is used to avoid an additional increment on release when the timer was used to increment the variable.

      C Source Code

      1. #include "DIALOG.h"
      2. /*********************************************************************
      3. *
      4. * Static code
      5. *
      6. **********************************************************************
      7. */
      8. /*********************************************************************
      9. *
      10. * _cbBk
      11. */
      12. static void _cbBk(WM_MESSAGE * pMsg) {
      13. int Id;
      14. int NCode;
      15. WM_HWIN hItem;
      16. static int Value;
      17. static int TimerInc;
      18. static WM_HTIMER hTimer;
      19. switch (pMsg->MsgId) {
      20. case WM_CREATE:
      21. hTimer = WM_CreateTimer(pMsg->hWin, 0, 0, 0);
      22. BUTTON_CreateEx(10, 10, 80, 20, pMsg->hWin, WM_CF_SHOW, 0, GUI_ID_BUTTON0);
      23. hItem = TEXT_CreateEx(100, 10, 80, 20, pMsg->hWin, WM_CF_SHOW, 0, GUI_ID_TEXT0, "0");
      24. TEXT_SetTextColor(hItem, GUI_WHITE);
      25. TEXT_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
      26. TEXT_SetDec(hItem, 0, 5, 0, 0, 1);
      27. break;
      28. case WM_PAINT:
      29. GUI_SetBkColor(GUI_BLACK);
      30. GUI_Clear();
      31. break;
      32. case WM_TIMER:
      33. hItem = WM_GetDialogItem(pMsg->hWin, GUI_ID_BUTTON0);
      34. if (BUTTON_IsPressed(hItem)) {
      35. hItem = WM_GetDialogItem(pMsg->hWin, GUI_ID_TEXT0);
      36. Value++;
      37. TEXT_SetDec(hItem, Value, 5, 0, 0, 1);
      38. WM_RestartTimer(hTimer, 25);
      39. TimerInc = 1;
      40. } else {
      41. TimerInc = 0;
      42. }
      43. break;
      44. case WM_NOTIFY_PARENT:
      45. Id = WM_GetId(pMsg->hWinSrc);
      46. NCode = pMsg->Data.v;
      47. switch (Id) {
      48. case GUI_ID_BUTTON0:
      49. switch (NCode) {
      50. case WM_NOTIFICATION_CLICKED:
      51. WM_RestartTimer(hTimer, 200);
      52. break;
      53. case WM_NOTIFICATION_RELEASED:
      54. if (TimerInc == 0) {
      55. hItem = WM_GetDialogItem(pMsg->hWin, GUI_ID_TEXT0);
      56. Value++;
      57. TEXT_SetDec(hItem, Value, 5, 0, 0, 1);
      58. }
      59. break;
      60. }
      61. break;
      62. }
      63. break;
      64. default:
      65. WM_DefaultProc(pMsg);
      66. break;
      67. }
      68. }
      69. /*********************************************************************
      70. *
      71. * Public code
      72. *
      73. **********************************************************************
      74. */
      75. /*********************************************************************
      76. *
      77. * MainTask
      78. */
      79. void MainTask(void) {
      80. GUI_Init();
      81. WM_MULTIBUF_Enable(1);
      82. WM_CreateWindowAsChild(0, 0, LCD_GetXSize(), LCD_GetYSize(), WM_HBKWIN, WM_CF_SHOW, _cbBk, 0);
      83. while (1) {
      84. GUI_Delay(100);
      85. }
      86. }
      87. /*************************** End of file ****************************/
      Display All

      Regards,
      Sven
    • Hi Sven,

      It works great, thanks! :D

      More more question: if I want to have several BUTTONS with their corresponding TIMERs in the same window, that behave as the above, I suppose that when I get a WM_TIMER trigger, I need to a way to find out which TIMER reached it's period? I assume that the "UserId" from the function: WM_HTIMER WM_CreateTimer(WM_HWIN hWin, int UserId, int Period, int Mode), will give me that, right? Because this UserId should tell me which TIMER (and it's corresponding BUTTON) reached it's period.

      Of course, I'm assuming that all the BUTTONs will be created in the same Callback function (_cbBk). Maybe this is not possible? If it is, how can I find out which timer reached it's period?

      Thanks again!
      E4M
    • Hi Sven,

      I solved it! No need to spend time on this. (I mean the previous question about having several buttons. The question, about using the ESCAPE key, below, I have not solved yet and need your help).

      I'm using the emWIN example, per below, to use the ESCAPE key to exit. But when I press the ESCAPE key nothing happens.
      If I place a break point at the "switch(pMsg->MsgId);" statement, run the program and press ESCAPE, nothing happens and
      the break point is not even hit (I don't even get a callback trigger when I hit ESCAPE). Do I need to call any other emWIN
      function before emWIN will react on pressed keys?

      static void _cbBk(WM_MESSAGE * pMsg) {
      ...
      ...

      switch (pMsg->MsgId) {
      case WM_KEY: //
      switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key) {
      case GUI_KEY_ESCAPE:
      _Break = 1;
      break;
      }
      break;
      ----

      Thanks
      E4M

      The post was edited 1 time, last by Electrons4me ().

    • Hi Sven,

      In the example you provided up above on the 9th of jan 2020, I simply added in the WM_PAINT: the following DrawVLine() statement:

      static int Value = 20;
      ...
      ...

      case WM_PAINT:
      GUI_SetBkColor(GUI_BLACK);
      GUI_Clear();
      GUI_DrawVLine(Value, 70, 135); <--------
      break;

      When I click on the Button I need to have the vertical line move from left to right as the variable "Value" increments. Now I've attached a screen shot of the result. I clicked the Button several times Value went from 20 to 101 but the line does move (it's at the initial position when "Value" was equal to 20). I thought that every time I clicked the button, the case WM_PAINT would be called, the GUI_Clear() would erase the Child window and a new line would be drawn, in the Child window, at the incremented value of x= Value. That does not happen.

      Is my logic above correct? If I'm wrong, what do I need to do for the Vertical line to be redrawn as a function of the changing value of the variable "Value"?

      (Note: I did not modify anything else on your original code that you provided. I just added the single GUI_DrawVLine(Value, 70, 135); )

      I have gone through the User Manual and searched for a way to draw a line in a Child Window but I could not find any examples for that.
      I also searched in the Segger emWIN forum and found the post:
      forum.segger.com/index.php/Thr…Bchild%2Bwindow#post11869

      But even this post does show how to "simply" draw a line in the code that I got from you, although it should be straightforward that if I'm drawing a line in the case WM_PAINT: of the callback of the Child Window emWIN should know to draw in that specific Child Window.

      Please help me figure out where my logic is wrong.

      Thanks
      E4M
      Images
      • Capture.PNG

        73.92 kB, 617×448, viewed 8 times

      The post was edited 2 times, last by Electrons4me ().