text: /*********************************************************************
  *                    SEGGER Microcontroller GmbH                     *
  *        Solutions for real time microcontroller applications        *
  **********************************************************************
  *                                                                    *
  *        (c) 1996 - 2019  SEGGER Microcontroller GmbH                *
  *                                                                    *
  *        Internet: www.segger.com    Support:  support@segger.com    *
  *                                                                    *
  **********************************************************************
  
  ** emWin V5.50 - Graphical user interface for embedded applications **
  emWin is protected by international copyright laws.   Knowledge of the
  source code may not be used to write a similar product.  This file may
  only  be used  in accordance  with  a license  and should  not be  re-
  distributed in any way. We appreciate your understanding and fairness.
  ----------------------------------------------------------------------
  File        : WIDGET_EffectVGA.c
  Purpose     : Example demonstrating the use of widget effects
  Requirements: WindowManager - (x)
                MemoryDevices - (x)
                AntiAliasing  - ( )
                VNC-Server    - ( )
                PNG-Library   - ( )
                TrueTypeFonts - ( )
  ----------------------------------------------------------------------
  */
  
  #include <stdlib.h>
  #include <stddef.h>
  #include <string.h>
  #include "GUI.h"
  #include "DIALOG.h"
  #include "PROGBAR.h"
  #include "LISTVIEW.h"
  #include "GRAPH.h"
  #include "MULTIPAGE.h"
  #include "MENU.h"
  #include "LCDConf.h"
  #include "GUIConf.h"
  
  #if !defined(WIDGET_USE_SCHEME_LARGE)
    #error Wrong scheme selected!
  #endif
  
  /*********************************************************************
  *
  *       Defines
  *
  **********************************************************************
  */
  #define NUM_WIDGETS         GUI_COUNTOF(_aID)
  #define ID_MENU             (GUI_ID_USER +  0)
  #define ID_MENU_FILE_NEW    (GUI_ID_USER +  1)
  #define ID_MENU_FILE_OPEN   (GUI_ID_USER +  2)
  #define ID_MENU_FILE_CLOSE  (GUI_ID_USER +  3)
  #define ID_MENU_FILE_EXIT   (GUI_ID_USER +  4)
  #define ID_MENU_FILE_RECENT (GUI_ID_USER +  5)
  #define ID_MENU_RECENT_0    (GUI_ID_USER +  6)
  #define ID_MENU_RECENT_1    (GUI_ID_USER +  7)
  #define ID_MENU_RECENT_2    (GUI_ID_USER +  8)
  #define ID_MENU_RECENT_3    (GUI_ID_USER +  9)
  #define ID_MENU_EDIT_UNDO   (GUI_ID_USER + 10)
  #define ID_MENU_EDIT_REDO   (GUI_ID_USER + 11)
  #define ID_MENU_EDIT_COPY   (GUI_ID_USER + 12)
  #define ID_MENU_EDIT_PASTE  (GUI_ID_USER + 13)
  #define ID_MENU_EDIT_DELETE (GUI_ID_USER + 14)
  #define ID_MENU_HELP_ABOUT  (GUI_ID_USER + 15)
  
  //
  // Recommended memory to run the sample with adequate performance
  //
  #define RECOMMENDED_MEMORY (1024L * 60)
  
  /*********************************************************************
  *
  *       Static data
  *
  **********************************************************************
  */
  //
  // Dialog resource of main dialog box
  //
  static const GUI_WIDGET_CREATE_INFO _aDlgWidgets[] = {
    { WINDOW_CreateIndirect,    "",             0,                    0,   0, 690, 435, 0},
    { TEXT_CreateIndirect,      "Progress bar",  GUI_ID_TEXT0,       10,  35, 120,  25, TEXT_CF_HCENTER},
    { PROGBAR_CreateIndirect,   NULL,            GUI_ID_PROGBAR0,    10,  60, 120,  25 },
    { TEXT_CreateIndirect,      "Button",        GUI_ID_TEXT0,       10,  90, 120,  25, TEXT_CF_HCENTER},
    { BUTTON_CreateIndirect,    "Button",        GUI_ID_BUTTON0,     10, 115, 120,  25 },
    { TEXT_CreateIndirect,      "Dropdown",      GUI_ID_TEXT0,       10, 145, 120,  25, TEXT_CF_HCENTER},
    { DROPDOWN_CreateIndirect,  NULL,            GUI_ID_DROPDOWN0,   10, 170, 120,  85, DROPDOWN_CF_AUTOSCROLLBAR},
    { TEXT_CreateIndirect,      "Edit",          GUI_ID_TEXT0,      150,  35, 120,  25, TEXT_CF_HCENTER},
    { EDIT_CreateIndirect,      NULL,            GUI_ID_EDIT0,      150,  60, 120,  25 },
    { TEXT_CreateIndirect,      "Listbox",       GUI_ID_TEXT0,      150,  90, 120,  25, TEXT_CF_HCENTER},
    { LISTBOX_CreateIndirect,   "",              GUI_ID_LISTBOX0,   150, 115, 120, 165, 0, 0 },
    { TEXT_CreateIndirect,      "Listview",      GUI_ID_TEXT0,      290,  35, 150,  25, TEXT_CF_HCENTER},
    { LISTVIEW_CreateIndirect,  NULL,            GUI_ID_LISTVIEW0,  290,  60, 150, 135, 0 },
    { TEXT_CreateIndirect,      "Multiedit",     GUI_ID_TEXT0,      290, 200, 150,  25, TEXT_CF_HCENTER},
    { MULTIEDIT_CreateIndirect, "",              GUI_ID_MULTIEDIT0, 290, 225, 150,  60, 0, 0 },
    { TEXT_CreateIndirect,      "Scrollbars",    GUI_ID_TEXT0,      460,  35, 100,  25, TEXT_CF_HCENTER},
    { SCROLLBAR_CreateIndirect, NULL,            GUI_ID_SCROLLBAR1, 460,  60,  20, 200, SCROLLBAR_CF_VERTICAL },
    { SCROLLBAR_CreateIndirect, NULL,            GUI_ID_SCROLLBAR2, 490,  60,  70, 200, SCROLLBAR_CF_VERTICAL },
    { SCROLLBAR_CreateIndirect, NULL,            GUI_ID_SCROLLBAR0, 460, 270, 100,  15, 0 },
    { TEXT_CreateIndirect,      "Sliders",       GUI_ID_TEXT0,      580,  35, 100,  25, TEXT_CF_HCENTER},
    { SLIDER_CreateIndirect,    NULL,            GUI_ID_SLIDER1,    580,  60,  20, 200, SLIDER_CF_VERTICAL },
    { SLIDER_CreateIndirect,    NULL,            GUI_ID_SLIDER2,    610,  60,  70, 200, SLIDER_CF_VERTICAL },
    { SLIDER_CreateIndirect,    NULL,            GUI_ID_SLIDER0,    580, 270, 100,  15, 0 },
    { TEXT_CreateIndirect,      "Graph",         GUI_ID_TEXT0,      210, 300, 175,  25, TEXT_CF_HCENTER},
    { GRAPH_CreateIndirect,     0,               GUI_ID_GRAPH0,     210, 325, 175, 100 },
    { TEXT_CreateIndirect,      "Multipage",     GUI_ID_TEXT0,      400, 300, 220,  25, TEXT_CF_HCENTER},
    { MULTIPAGE_CreateIndirect, "Multipage",     GUI_ID_MULTIPAGE0, 400, 325, 220, 100 },
  };
  //
  // Dialog resource of options dialog box
  //
  static const GUI_WIDGET_CREATE_INFO _aDlgOptions[] = {
    { FRAMEWIN_CreateIndirect,  "Effect", 0,                  10, 325, 185, 120,   0},
    { CHECKBOX_CreateIndirect,  NULL,     GUI_ID_CHECK0,       0,   2,  90,   0 },
    { RADIO_CreateIndirect,     NULL,     GUI_ID_RADIO0,      80,   2,  95, 100,   0,  0x1e03 },
  };
  //
  // Dialog resource of first multipage window
  //
  static const GUI_WIDGET_CREATE_INFO _aDialogCreate1[] = {
    { WINDOW_CreateIndirect,    "Dialog 1", 0,                   0,   0, 260, 100  },
    { TEXT_CreateIndirect,      "Dialog 1", 0,                   5,   5,  80,  25, TEXT_CF_LEFT },
    { BUTTON_CreateIndirect,    "Button",   GUI_ID_BUTTON0,      5,  30,  80,  25, 0},
  };
  //
  // Dialog resource of second multipage window
  //
  static const GUI_WIDGET_CREATE_INFO _aDialogCreate2[] = {
    { WINDOW_CreateIndirect,    "Dialog 2", 0,                   0,   0, 260, 100, },
    { TEXT_CreateIndirect,      "Dialog 2", 0,                   5,   5,  80,  25, TEXT_CF_LEFT },
    { SLIDER_CreateIndirect,    "",         GUI_ID_SLIDER0,      5,  30, 200,  40  },
  };
  //
  // Array of widget ID's
  //
  static int _aID[] = { GUI_ID_BUTTON0,    GUI_ID_EDIT0,      GUI_ID_LISTBOX0,   GUI_ID_PROGBAR0,   
                        GUI_ID_LISTVIEW0,  GUI_ID_MULTIEDIT0, GUI_ID_DROPDOWN0,  GUI_ID_SCROLLBAR0, 
                        GUI_ID_SCROLLBAR1, GUI_ID_SCROLLBAR2, GUI_ID_SLIDER0,    GUI_ID_SLIDER1,    
                        GUI_ID_SLIDER2,    GUI_ID_GRAPH0,     GUI_ID_MULTIPAGE0};
  //
  // Array of widget handles
  //
  static WM_HWIN _ahWin[GUI_COUNTOF(_aID)];
  //
  // Makes it easier to access the array _ahWin
  //
  enum { BUTTON0,    EDIT0,      LISTBOX0,   PROGBAR0, 
         LISTVIEW0,  MULTIEDIT0, DROPDOWN0,  SCROLLBAR0, 
         SCROLLBAR1, SCROLLBAR2, SLIDER0,    SLIDER1,    
         SLIDER2,    GRAPH0,     MULTIPAGE0};
  //
  // Array of available effects
  //
  const WIDGET_EFFECT * _apEffect[] = {&WIDGET_Effect_3D,     
                                       &WIDGET_Effect_Simple, 
                                       &WIDGET_Effect_None};
  //
  // Array of strings used to label the frame window
  //
  const char *   _apEffects[] = {"Widget effect: 3D",
                                 "Widget effect: Simple", 
                                 "Widget effect: None"};
  //
  // Used for graph widget
  //
  static I16                _aValue[3];                                      // Array of values to be added
  static GRAPH_DATA_Handle  _ahData[3];                                      // Array of handles for the GRAPH_DATA objects
  static GUI_COLOR          _aColor[] = {GUI_RED, GUI_GREEN, GUI_LIGHTBLUE}; // Array of colors for the GRAPH_DATA objects
  static WM_HWIN            _hDlg;
  static WM_HWIN            _hFrameWin;
  static int                _AutoMode = 1;
  
  /*********************************************************************
  *
  *       Static code
  *
  **********************************************************************
  */
  /*********************************************************************
  *
  *       _AddValues
  *
  * Function description
  *   This routine calculates new random values in dependence of the previous added values
  *   and adds them to the GRAPH_DATA objects
  */
  static void _AddValues(int MaxValue) {
    unsigned i;
  
    for (i = 0; i < GUI_COUNTOF(_aValue); i++) {
      int Add = rand() % (2 + i * i);
      int Vz  = ((rand() % 2) << 1) - 1;
      _aValue[i] += Add * Vz;
      if (_aValue[i] > MaxValue) {
        _aValue[i] = MaxValue;
      } else if (_aValue[i] < 0) {
        _aValue[i] = 0;
      }
      GRAPH_DATA_YT_AddValue(_ahData[i], _aValue[i]);
    }
  }
  
  /*********************************************************************
  *
  *       _SetWidgetEffect
  *
  * Function description
  *   Sets the effect for the given widget and recursive for its child windows
  */
  static void _SetWidgetEffect(WM_HWIN hWin, const WIDGET_EFFECT * pEffect) {
    WM_HWIN hChild;
  
    if (hWin) {
      WIDGET_SetEffect(hWin, pEffect); /* Set effect for the widget*/
      //
      // Iterate over the child windows
      //
      hChild = WM_GetFirstChild(hWin);
      while (hChild) {
        _SetWidgetEffect(hChild, pEffect); /* Set effect for the child windows */
        hChild = WM_GetNextSibling(hChild);
      }
    }
  }
  
  /*********************************************************************
  *
  *       _SetEffect
  */
  static void _SetEffect(int Index) {
    unsigned              i;
    const WIDGET_EFFECT * pEffect;
  
    pEffect = _apEffect[Index];
    WIDGET_SetDefaultEffect(pEffect);
    FRAMEWIN_SetText(_hFrameWin, _apEffects[Index]);
    //
    // Iterate over all dialog widgets
    //
    for (i = 0; i < NUM_WIDGETS; i++) {
      _SetWidgetEffect(_ahWin[i], _apEffect[Index]); /* Set effect */
    }
  }
  
  /*********************************************************************
  *
  *       _AddMenuItem
  */
  static void _AddMenuItem(MENU_Handle hMenu, MENU_Handle hSubmenu, const char* pText, U16 Id, U16 Flags) {
    MENU_ITEM_DATA Item;
  
    Item.pText    = pText;
    Item.hSubmenu = hSubmenu;
    Item.Flags    = Flags;
    Item.Id       = Id;
    MENU_AddItem(hMenu, &Item);
  }
  
  /*********************************************************************
  *
  *       _CreateMenu
  */
  static WM_HWIN _CreateMenu(WM_HWIN hParent) {
    MENU_Handle hMenu;
    MENU_Handle hMenuFile;
    MENU_Handle hMenuEdit;
    MENU_Handle hMenuHelp;
    MENU_Handle hMenuRecent;
    //
    // Create main menu
    //
    hMenu       = MENU_CreateEx(0, 0, 0, 0, WM_UNATTACHED, 0, MENU_CF_HORIZONTAL, ID_MENU);
    //
    // Create sub menus
    //
    hMenuFile   = MENU_CreateEx(0, 0, 0, 0, WM_UNATTACHED, 0, MENU_CF_VERTICAL, 0);
    hMenuEdit   = MENU_CreateEx(0, 0, 0, 0, WM_UNATTACHED, 0, MENU_CF_VERTICAL, 0);
    hMenuHelp   = MENU_CreateEx(0, 0, 0, 0, WM_UNATTACHED, 0, MENU_CF_VERTICAL, 0);
    hMenuRecent = MENU_CreateEx(0, 0, 0, 0, WM_UNATTACHED, 0, MENU_CF_VERTICAL, 0);
    //
    // Add menu items to menu 'Recent'
    //
    _AddMenuItem(hMenuRecent, 0,           "File 0",   ID_MENU_RECENT_0,    0);
    _AddMenuItem(hMenuRecent, 0,           "File 1",   ID_MENU_RECENT_1,    0);
    _AddMenuItem(hMenuRecent, 0,           "File 2",   ID_MENU_RECENT_2,    0);
    _AddMenuItem(hMenuRecent, 0,           "File 3",   ID_MENU_RECENT_3,    0);
    //
    // Add menu items to menu 'File'
    //
    _AddMenuItem(hMenuFile,   0,           "New",      ID_MENU_FILE_NEW,    0);
    _AddMenuItem(hMenuFile,   0,           "Open",     ID_MENU_FILE_OPEN,   0);
    _AddMenuItem(hMenuFile,   0,           "Close",    ID_MENU_FILE_CLOSE,  0);
    _AddMenuItem(hMenuFile,   0,           0,          0,                   MENU_IF_SEPARATOR);
    _AddMenuItem(hMenuFile,   hMenuRecent, "Files...", ID_MENU_FILE_RECENT, 0);
    _AddMenuItem(hMenuFile,   0,           0,          0,                   MENU_IF_SEPARATOR);
    _AddMenuItem(hMenuFile,   0,           "Exit",     ID_MENU_FILE_EXIT,   0);
    //
    // Add menu items to menu 'Edit'
    //
    _AddMenuItem(hMenuEdit,   0,           "Undo",     ID_MENU_EDIT_UNDO,   0);
    _AddMenuItem(hMenuEdit,   0,           "Redo",     ID_MENU_EDIT_REDO,   0);
    _AddMenuItem(hMenuEdit,   0,           0,          0,                   MENU_IF_SEPARATOR);
    _AddMenuItem(hMenuEdit,   0,           "Copy",     ID_MENU_EDIT_COPY,   0);
    _AddMenuItem(hMenuEdit,   0,           "Paste",    ID_MENU_EDIT_PASTE,  0);
    _AddMenuItem(hMenuEdit,   0,           "Delete",   ID_MENU_EDIT_DELETE, 0);
    //
    // Add menu items to menu 'Help'
    //
    _AddMenuItem(hMenuHelp,   0,           "About",    ID_MENU_HELP_ABOUT,  0);
    //
    // Add menu items to main menu
    //
    _AddMenuItem(hMenu,       hMenuFile,   "File",     0,                   0);
    _AddMenuItem(hMenu,       hMenuEdit,   "Edit",     0,                   0);
    _AddMenuItem(hMenu,       hMenuHelp,   "Help",     0,                   0);
    //
    // Attach menu to parent window
    //
    MENU_Attach(hMenu, hParent, 0, 0, WM_GetWindowSizeX(hParent), 0, 0);
    return hMenu;
  }
  
  /*********************************************************************
  *
  *       _cbBkWindow
  */
  static void _cbBkWindow(WM_MESSAGE * pMsg) {
    switch (pMsg->MsgId) {
    case WM_PAINT:
      GUI_SetBkColor(GUI_BLUE);
      GUI_Clear();
      GUI_SetColor(GUI_WHITE);
      GUI_SetFont(&GUI_Font24_ASCII);
      GUI_DispStringHCenterAt("WIDGET_Effect - Sample", 160, 5);
      break;
    default:
      WM_DefaultProc(pMsg);
    }
  }
  
  /*********************************************************************
  *
  *       _cbDialogPage
  *
  * Function description
  *   Dialog routine for multi page windows
  */
  static void _cbDialogPage(WM_MESSAGE * pMsg) {
    WM_DefaultProc(pMsg);
  }
  
  /*********************************************************************
  *
  *       _cbCallbackWidgets
  *
  * Function description
  *   Initializes the widgets of the main dialog box
  */
  static void _cbCallbackWidgets(WM_MESSAGE * pMsg) {
    GRAPH_SCALE_Handle hScaleH;
    GRAPH_SCALE_Handle hScaleV;
    WM_HWIN            hDlg;
    unsigned           i;
  
    hDlg = pMsg->hWin;
    switch (pMsg->MsgId) {
      case WM_INIT_DIALOG:
        //
        // Get handles of widgets
        //
        for (i = 0; i < NUM_WIDGETS; i++) {
          _ahWin[i] = WM_GetDialogItem(hDlg, _aID[i]);
        }
        //
        // Init dropdown widget
        //
        for (i = 0; i < 8; i++) {
          char acBuffer[] = {"Item x"};
          int Len = strlen(acBuffer);
          acBuffer[Len - 1] = '1' + i;
          DROPDOWN_AddString(_ahWin[DROPDOWN0], acBuffer);
        }
        //
        // Init edit widget
        //
        EDIT_SetText(_ahWin[EDIT0], "Edit");
        //
        // Init listbox widget
        //
        LISTBOX_SetAutoScrollV(_ahWin[LISTBOX0], 1);
        for (i = 0; i < 4; i++) {
          char acBuffer[] = {"Item x"};
          int Len = strlen(acBuffer);
          acBuffer[Len - 1] = '1' + i;
          LISTBOX_AddString(_ahWin[LISTBOX0], acBuffer);
        }
        //
        // Init listview widget
        //
        for (i = 0; i < 2; i++) {
          char acBuffer[] = {"Col. x"};
          int Len = strlen(acBuffer);
          acBuffer[Len - 1] = '1' + i;
          LISTVIEW_AddColumn(_ahWin[LISTVIEW0], 60, acBuffer, GUI_TA_CENTER);
        }
        for (i = 0; i < 9; i++) {
          int j;
          LISTVIEW_AddRow(_ahWin[LISTVIEW0], NULL);
          for (j = 0; j < (int)LISTVIEW_GetNumColumns(_ahWin[LISTVIEW0]); j++) {
            char acBuffer[] = {"Rx/Cx"};
            acBuffer[1] = '1' + i;
            acBuffer[4] = '1' + j;
            LISTVIEW_SetItemText(_ahWin[LISTVIEW0], j, i, acBuffer);
          }
        }
        LISTVIEW_SetGridVis(_ahWin[LISTVIEW0], 1);
        SCROLLBAR_CreateAttached(_ahWin[LISTVIEW0], SCROLLBAR_CF_VERTICAL);
        //
        // Init multiedit widget
        //
        MULTIEDIT_SetText(_ahWin[MULTIEDIT0], "This text could be modified by the MULTIEDIT widget");
        MULTIEDIT_SetWrapWord(_ahWin[MULTIEDIT0]);
        MULTIEDIT_SetAutoScrollV(_ahWin[MULTIEDIT0], 1);
        //
        // Init progbar widget
        //
        WIDGET_SetEffect(_ahWin[PROGBAR0], &WIDGET_Effect_3D);
        //
        // Init graph widget
        //
        for (i = 0; i < GUI_COUNTOF(_aColor); i++) {
          _aValue[i] = rand() % 95;
          _ahData[i] = GRAPH_DATA_YT_Create(_aColor[i], 500, 0, 0);
          GRAPH_AttachData(_ahWin[GRAPH0], _ahData[i]);
        }
        GRAPH_SetGridDistY(_ahWin[GRAPH0], 25);
        GRAPH_SetGridVis(_ahWin[GRAPH0], 1);
        GRAPH_SetGridFixedX(_ahWin[GRAPH0], 1);
        GRAPH_SetBorder(_ahWin[GRAPH0], 20, 4, 5, 4);
        //
        // Create and add vertical scale of graph widget
        //
        hScaleV = GRAPH_SCALE_Create(18, GUI_TA_RIGHT, GRAPH_SCALE_CF_VERTICAL, 25);
        GRAPH_SCALE_SetTextColor(hScaleV, GUI_RED);
        GRAPH_AttachScale(_ahWin[GRAPH0], hScaleV);
        //
        // Create and add horizontal scale of graph widget
        //
        hScaleH = GRAPH_SCALE_Create(46, GUI_TA_HCENTER | GUI_TA_VCENTER, GRAPH_SCALE_CF_HORIZONTAL, 50);
        GRAPH_SCALE_SetTextColor(hScaleH, GUI_DARKGREEN);
        GRAPH_AttachScale(_ahWin[GRAPH0], hScaleH);
        //
        // Init multipage widget
        //
        MULTIPAGE_AddPage(_ahWin[MULTIPAGE0],
                          GUI_CreateDialogBox(_aDialogCreate1, GUI_COUNTOF(_aDialogCreate1), &_cbDialogPage, WM_UNATTACHED, 0, 0), 
                          "Page 1");
        MULTIPAGE_AddPage(_ahWin[MULTIPAGE0],
                          GUI_CreateDialogBox(_aDialogCreate2, GUI_COUNTOF(_aDialogCreate2), &_cbDialogPage, WM_UNATTACHED, 0, 0), 
                          "Page 2");
        //
        // Create and attach menu
        //
        _CreateMenu(hDlg);
        break;
      default:
        WM_DefaultProc(pMsg);
    }
  }
  
  /*********************************************************************
  *
  *       _cbCallbackFramewin
  *
  * Function description
  *   Handles the scroll messages of the scrollbar
  */
  static void _cbCallbackFramewin(WM_MESSAGE * pMsg) {
    WM_HWIN hDlg;
  
    hDlg = pMsg->hWin;
    switch (pMsg->MsgId) {
      case WM_NOTIFY_PARENT:
        if (pMsg->Data.v == WM_NOTIFICATION_VALUE_CHANGED) {
          if (pMsg->hWinSrc == WM_GetScrollbarH(hDlg)) {
            int xPos, yPos;
            WM_SCROLL_STATE ScrollState;
            WM_GetScrollState(pMsg->hWinSrc, &ScrollState);
            xPos = WM_GetWindowOrgX(WM_GetParent(_hDlg)) - ScrollState.v;
            yPos = WM_GetWindowOrgY(_hDlg);
            WM_MoveTo(_hDlg, xPos, yPos);
          }
        }
        break;
      default:
        WM_DefaultProc(pMsg);
    }
  }
  
  /*********************************************************************
  *
  *       _cbCallbackOptions
  *
  * Function description
  *   Callback of the options dialog box, sets the widget effects
  */
  static void _cbCallbackOptions(WM_MESSAGE * pMsg) {
    WM_HWIN hDlg;
    WM_HWIN hItem;
  
    hDlg = pMsg->hWin;
    switch (pMsg->MsgId) {
      case WM_INIT_DIALOG:
        //
        // Init check box
        //
        hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK0);
        CHECKBOX_Check(hItem);
        CHECKBOX_SetText(hItem, "Auto");
        //
        // Init radio button
        //
        hItem = WM_GetDialogItem(hDlg, GUI_ID_RADIO0);
        RADIO_SetText(hItem, "3D",     0);
        RADIO_SetText(hItem, "Simple", 1);
        RADIO_SetText(hItem, "None",   2);
        break;
      case WM_NOTIFY_PARENT:
        if (pMsg->Data.v == WM_NOTIFICATION_VALUE_CHANGED) {
          hItem = WM_GetDialogItem(hDlg, GUI_ID_RADIO0);
          if (pMsg->hWinSrc == hItem) {
            _SetEffect(RADIO_GetValue(hItem));
          }
        } else if (pMsg->Data.v == WM_NOTIFICATION_RELEASED) {
          hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK0);
          if (pMsg->hWinSrc == hItem) {
            _AutoMode = CHECKBOX_IsChecked(hItem);
          }
        }
        break;
      default:
        WM_DefaultProc(pMsg);
    }
  }
  
  /*********************************************************************
  *
  *       Public code
  *
  **********************************************************************
  */
  /*********************************************************************
  *
  *       MainTask
  */
  void MainTask(void) {
    GUI_RECT RectDlg;
    GUI_RECT RectClient;
    WM_HWIN  hScrollbar;
    WM_HWIN  hDlgOptions;
    int      Cnt;
    int      IndexEffect;
    int      ButtonState;
    int      DropdownState;
    int      ProgbarValue;
    int      ProgbarInc;
    int      SliderValue;
    int      SliderInc;
    int      ScrollbarValue;
    int      ScrollbarInc;
    int      ListViewInc;
    int      ListBoxInc;
    int      MultiEditInc;
    int      Vz;
    const char          * _apEffects[] = {"Widget effect: 3D", "Widget effect: Simple", "Widget effect: None"};
  
    Cnt            = 0;
    IndexEffect    = 0;
    ButtonState    = 0;
    DropdownState  = 0;
    ProgbarValue   = 0;
    ProgbarInc     = 1;
    SliderValue    = 0;
    SliderInc      = 1;
    ScrollbarValue = 0;
    ScrollbarInc   = 1;
    ListViewInc    = 1;
    ListBoxInc     = 1;
    MultiEditInc   = 1;
    Vz             = 1;
    GUI_Init();
    //
    // Check if recommended memory for the sample is available
    //
    if (GUI_ALLOC_GetNumFreeBytes() < RECOMMENDED_MEMORY) {
      GUI_ErrorOut("Not enough memory available."); 
      return;
    }
    GUI_CURSOR_Show();
    WM_SetCallback(WM_HBKWIN, _cbBkWindow);
    WM_SetCreateFlags(WM_CF_MEMDEV);  // Use memory devices on all windows to avoid flicker
    WM_EnableMemdev(WM_HBKWIN);       // Enable use of memory devices for desktop windows
    //
    // Create framewindow and set its properties
    //
    _hFrameWin = FRAMEWIN_CreateEx(0, 0, 640, 480, 0, WM_CF_SHOW, 0, 0, "", &_cbCallbackFramewin);
    FRAMEWIN_SetMoveable(_hFrameWin, 1);
    FRAMEWIN_SetText(_hFrameWin, _apEffects[0]);
    FRAMEWIN_SetFont(_hFrameWin, &GUI_Font13B_ASCII);
    //
    // Create main dialog window as child from framewindows client window
    //
    _hDlg = GUI_CreateDialogBox(_aDlgWidgets,
                                GUI_COUNTOF(_aDlgWidgets), 
                                &_cbCallbackWidgets, 
                                WM_GetClientWindow(_hFrameWin), 0, 0);
    //
    // Attach scrollbar to framewindows client window and set its properties
    //
    hScrollbar = SCROLLBAR_CreateAttached(WM_GetClientWindow(_hFrameWin), 0);
    WM_GetWindowRectEx(_hDlg, &RectDlg);
    WM_GetClientRectEx(WM_GetClientWindow(_hFrameWin), &RectClient);
    SCROLLBAR_SetNumItems(hScrollbar, RectDlg.x1);
    SCROLLBAR_SetPageSize(hScrollbar, RectClient.x1);
    //
    // Create options dialog with 'stay on top' and 'moveable' attribute
    //
    hDlgOptions = GUI_CreateDialogBox(_aDlgOptions, 
                                      GUI_COUNTOF(_aDlgOptions), 
                                      &_cbCallbackOptions, 
                                      WM_HBKWIN, 0, 0);
    FRAMEWIN_SetMoveable(hDlgOptions, 1);
    WM_SetStayOnTop(hDlgOptions, 1);
    //
    // Main loop for modifying the widgets
    //
    while (1) {
      if (_AutoMode) {
        Cnt++;
        //
        // Modify progbar
        //
        if ((Cnt % 2) == 0) {
          ProgbarValue += ProgbarInc;
          if ((ProgbarValue == 110) || (ProgbarValue == -10)) {
            ProgbarInc *= -1;
          }
          PROGBAR_SetValue(_ahWin[PROGBAR0], ProgbarValue);
        }
        //
        // Modify slider
        //
        if ((Cnt % 2) == 0) {
          int j;
  
          SliderValue += SliderInc;
          if ((SliderValue == 100) || (SliderValue == 0)) {
            SliderInc *= -1;
          }
          for (j = 0; j < 3; j++) {
            SLIDER_SetValue(_ahWin[SLIDER0 + j], SliderValue);
          }
        }
        //
        // Modify scrollbar
        //
        if ((Cnt % 3) == 0) {
          int j;
  
          ScrollbarValue += ScrollbarInc;
          if ((ScrollbarValue == 90) || (ScrollbarValue == 0)) {
            ScrollbarInc *= -1;
          }
          for (j = 0; j < 3; j++) {
            SCROLLBAR_SetValue(_ahWin[SCROLLBAR0 + j], ScrollbarValue);
          }
        }
        //
        // Modify multipage
        //
        if ((Cnt % 120) == 0) {
          MULTIPAGE_SelectPage(_ahWin[MULTIPAGE0], MULTIPAGE_GetSelection(_ahWin[MULTIPAGE0]) ^ 1);
        }
        //
        // Modify dropdown
        //
        if ((Cnt % 120) == 0) {
          DropdownState ^= 1;
          if (DropdownState) {
            DROPDOWN_Expand(_ahWin[DROPDOWN0]);
          } else {
            DROPDOWN_Collapse(_ahWin[DROPDOWN0]);
          }
        }
        //
        // Modify button
        //
        if ((Cnt % 40) == 0) {
          ButtonState ^= 1;
          BUTTON_SetPressed(_ahWin[BUTTON0], ButtonState);
        }
        //
        // Modify listbox
        //
        if ((Cnt % 30) == 0) {
          int Sel;
  
          Sel = LISTBOX_GetSel(_ahWin[LISTBOX0]);
          if (Sel < 0) {
            Sel = 0;
          }
          LISTBOX_SetSel(_ahWin[LISTBOX0], Sel + ListBoxInc);
          Sel = LISTBOX_GetSel(_ahWin[LISTBOX0]);
          if ((Sel == (int)LISTBOX_GetNumItems(_ahWin[LISTBOX0]) - 1) || (Sel == 0)) {
            ListBoxInc *= -1;
          }
        }
        //
        // Modify listview
        //
        if ((Cnt % 50) == 0) {
          int Sel;
  
          Sel = LISTVIEW_GetSel(_ahWin[LISTVIEW0]);
          if (Sel < 0) {
            Sel = 0;
          }
          LISTVIEW_SetSel(_ahWin[LISTVIEW0], Sel + ListViewInc);
          Sel = LISTVIEW_GetSel(_ahWin[LISTVIEW0]);
          if ((Sel == (int)LISTVIEW_GetNumRows(_ahWin[LISTVIEW0]) - 1) || (Sel == 0)) {
            ListViewInc *= -1;
          }
        }
        //
        // Modify multiedit
        //
        if ((Cnt % 5) == 0) {
          int  Sel;
          int  Len;
          char acBuffer[100];
  
          MULTIEDIT_SetCursorOffset(_ahWin[MULTIEDIT0], MULTIEDIT_GetCursorCharPos(_ahWin[MULTIEDIT0]) + MultiEditInc);
          MULTIEDIT_GetText(_ahWin[MULTIEDIT0], acBuffer, sizeof(acBuffer));
          Sel = MULTIEDIT_GetCursorCharPos(_ahWin[MULTIEDIT0]);
          Len = strlen(acBuffer);
          if ((Sel == (Len - 1)) || (Sel == 0)) {
            MultiEditInc *= -1;
          }
          if (!DropdownState) {
            WM_SetFocus(_ahWin[MULTIEDIT0]);
          }
        }
        //
        // Modify graph
        //
        _AddValues(95);
        //
        // Move window
        //
        if ((Cnt % 1200) == 0) {
          int             Inc;
          WM_HWIN         hScroll;
          WM_SCROLL_STATE ScrollState;
  
          hScroll = WM_GetScrollbarH(WM_GetClientWindow(_hFrameWin));
          WM_GetScrollState(hScroll, &ScrollState);
          Inc = (ScrollState.NumItems - ScrollState.PageSize) / 2;
          ScrollState.v += Inc * Vz;
          if ((ScrollState.v >= Inc * 2) || (ScrollState.v <= 0)) {
            Vz *= -1;
          }
          SCROLLBAR_SetValue(hScroll, ScrollState.v);
        }
        //
        // Change effect
        //
        if ((Cnt % 400) == 0) {
          int     Index;
          WM_HWIN hWin;
  
          IndexEffect++;
          Index = IndexEffect % GUI_COUNTOF(_apEffect);
          _SetEffect(Index);
          hWin = WM_GetDialogItem(hDlgOptions, GUI_ID_RADIO0);
          RADIO_SetValue(hWin, Index);
        }
      }
      //
      // Wait a while
      //
      GUI_Delay(10);
    }
  }
  
  /*************************** End of file ****************************/
  
  