Help with GUI design - Background Image with menus/sub-menus

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

    • Help with GUI design - Background Image with menus/sub-menus


      I'm using STemWin on my current project which is using an STM32H7, 800x480 TFT, using the LTDC controller.

      I'm trying to determine the correct approach to creating this type of design, which I figured I would creating using 2 emWin layers.

      1) layer0 - contains full size window that is painted with a full size bmp image (background)

      2) layer1 - contains multiple windows (they will be menus) that each have different widgets within them (laying them out using the GUIBuilder).

      ** I would like these windows to be TRANSPARENT except for their associated widgets** (when I enable the window of course...)

      I have the intial layer0 window working fine, painting the full background 800x480 bmp image.

      What I would like to is have all of these layer1 windows be TRANSPARENT except for their associated widgets, want them to show on top of course. But these windows (menus) will all be different menus or sub-menus, so only 1 of them will be shown at a time, depending on buttons of the current menu being pressed.

      First, is this the right approach to being able to do this?
      ie can I make the entire layer1 window area be TRANSPARENT (except for it's child widgets), and have the layer0 image showing through with the layer1 window's 'widgets' showing on top of the image?

      (I was assuming I can just do the 'WINDOW_SetBkColor(GUI_TRANSPARENT) for the layer1 window)

      So essentially I'll be displaying buttons that will then toggle other menus/sub-menus, etc..

      Is this the correct approach to doing a standard GUI like this?

      Or should I be creating ALL of my widgets,and attaching them to the layer0 window as children, and hiding/showing them individually, versus showing/disabling an entire window (which contains it's child widgets)?
    • Hi,

      since you habe created the Windows on layer 1 with the GUIBuilder try the following.

      The output of the GUIBuilder includes a callback function named _cbDialog(). Try if it works when adding the following:

      Source Code

      1. case WM_INIT_DIALOG:
      2. WM_SetHasTrans(pMsg->hWin);
      3. break;
      4. case WM_PAINT:
      5. GUI_SetBkColor(GUI_TRANSPARENT);
      6. GUI_Clear();
      7. break;

      Of course, layer 1 has to use a color conversion which supports transparency.

    • Hi Sven,

      Awesome, thanks so much, yeah, I'm using an LCDConf.c that is basically from one of the examples from STM, so their layer0 and 1 are setup as:

      Source Code

      1. /* Define Layer 0 color mode, orientation and sizes */
      2. #define COLOR_MODE_0 CMS_RGB565
      3. #define ORIENTATION_0 ROTATION_0
      4. #define XSIZE_0 640
      5. #define YSIZE_0 480
      6. /* Define Layer 1 color mode, orientation and sizes */
      7. #define COLOR_MODE_1 CMS_ARGB4444
      8. #define ORIENTATION_1 ROTATION_0
      9. #define XSIZE_1 640
      10. #define YSIZE_1 480
      Display All
      I had a feeling what I was missing was that trans setup, I wasn't doing that:


      Going to try this tonight, and I'll report back! Thanks so much!
    • Ok,

      No luck... I'm now just trying something simple, creating the two dialog boxes, not caring about transparency at this point, just want it to show layer1 over layer 0, but it seems layer1 just doesn't do anything to the framebuffer, it's WM_PAINT callback does get called, but nothing is drawn.

      If I create both dialog boxes on layer0, then it does draw both of them..

      so I must be doing someething stupid that I missed? I have GUI_NUM_LAYERs AS 2, and NUM_BUFFERS as 1, as I only have enough external SRAM right now for 1 frambuffer, not more..

      Source Code

      1. #define ID_WINDOW_0 (GUI_ID_USER + 0x00)
      2. #define ID_WINDOW_1 (GUI_ID_USER + 0x01)
      3. #define ID_BUTTON_1 (GUI_ID_USER + 0x02)
      4. static const GUI_WIDGET_CREATE_INFO _aDialogCreate0[] = {
      5. { WINDOW_CreateIndirect, "Window", ID_WINDOW_0, 0, 0, 800, 480, 0, 0x0, 0 },
      6. };
      7. static const GUI_WIDGET_CREATE_INFO _aDialogCreate1[] = {
      8. { WINDOW_CreateIndirect, "Window", ID_WINDOW_1, 0, 0, 800, 480, 0, 0x0, 0 },
      9. { BUTTON_CreateIndirect, "Button", ID_BUTTON_1, 410, 195, 130, 50, 0, 0x0, 0 },
      10. };
      11. static void _cbDialog0(WM_MESSAGE * pMsg)
      12. {
      13. WM_HWIN hItem;
      14. uint32_t FileSize = g_PeriphCtrl.BkGdInfo.FileSize;
      15. switch (pMsg->MsgId)
      16. {
      17. case WM_PAINT:
      18. UpdateFrameBufferImage();
      19. break;
      20. case WM_INIT_DIALOG:
      21. break;
      22. default:
      23. WM_DefaultProc(pMsg);
      24. break;
      25. }
      26. }
      27. static void _cbDialog1(WM_MESSAGE * pMsg)
      28. {
      29. WM_HWIN hItem;
      30. int NCode;
      31. int Id;
      32. switch (pMsg->MsgId)
      33. {
      34. case WM_INIT_DIALOG:
      35. //WM_SetHasTrans(pMsg->hWin);
      36. //hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_1);
      37. //BUTTON_SetText(hItem, "Test1");
      38. break;
      39. case WM_PAINT:
      40. //GUI_SetBkColor(GUI_TRANSPARENT);
      41. //GUI_Clear();
      42. WM_DefaultProc(pMsg);
      43. break;
      44. case WM_NOTIFY_PARENT:
      45. Id = WM_GetId(pMsg->hWinSrc);
      46. NCode = pMsg->Data.v;
      47. switch(Id) {
      48. case ID_BUTTON_1:
      49. switch(NCode)
      50. {
      52. break;
      54. break;
      55. }
      56. break;
      57. }
      58. break;
      59. default:
      60. WM_DefaultProc(pMsg);
      61. break;
      62. }
      63. }
      64. /*********************************************************************
      65. *
      66. * Public code
      67. *
      68. **********************************************************************
      69. */
      70. /*********************************************************************
      71. *
      72. * CreateWindow
      73. */
      74. void TestCreateWindow(void)
      75. {
      76. WM_HWIN hWin1;
      77. WM_HWIN hWin2;
      78. /* Activate the use of memory device feature */
      79. WM_SetCreateFlags(WM_CF_MEMDEV);
      80. /* Init the STemWin GUI Library */
      81. GUI_Init();
      82. WM_MULTIBUF_Enable(1);
      83. /* select layer 0 */
      84. GUI_SelectLayer(0);
      85. hWin1 = GUI_CreateDialogBox(_aDialogCreate0, GUI_COUNTOF(_aDialogCreate0), _cbDialog0, WM_HBKWIN, 0, 0);
      86. /* select layer 1 */
      87. GUI_SelectLayer(1);
      88. hWin2 = GUI_CreateDialogBox(_aDialogCreate1, GUI_COUNTOF(_aDialogCreate1), _cbDialog1, WM_HBKWIN, 0, 0);
      89. while(1) {
      90. GUI_Exec();
      91. }
      92. }
      Display All
      *** FYI, the 'UpdateFrameBufferImage()' is a function that just copies my JPEG decoded image to the frame buffer, that works fine... but when dialog1 is created on layer1, the WM_PAINT doesn't draw anything to the framebuffer..

      Also, my LCDConf.c code I"m using is straight from the STMCube package, 'STemWin_SampleDemo'...

      in this example they have the layer color codes set as:

      Source Code

      1. #define COLOR_CONVERSION_0 GUICC_M565
      2. #define DISPLAY_DRIVER_0 GUIDRV_LIN_16
      3. #if (GUI_NUM_LAYERS > 1)
      4. #define COLOR_CONVERSION_1 GUICC_M1555I
      5. #define DISPLAY_DRIVER_1 GUIDRV_LIN_16
      6. #endif

      What has always confused me to this point is how STemWin is doing these Layers? Is it normally all just done in STemWin via software and merged to one physical frame buffer, or are you trying to actually use the 2 physical hardware layers that the LTDC has?

      For example, I see other STemWin examples out there that have windows defined at Layer(0), Layer(1), Layer(2), etc, so how does '3' windows related to the underlying hardware.. say if the underlying device (like in my case an STM32H7 with 2-layer LTDC), how is that correlation done between the 2-layer LTDC and STemWin code using 3 layers?

      *** Maybe I should just keep the 'GUI_NUM_LAYERS' as "1" ???? **** ie keep the hardware always using just a single physical layer, since STemWin can do the multi-layer internally?

      The post was edited 3 times, last by MikeFlyersFan ().

    • Ok,

      I keep re-reading the emWin User-Guide, I think I'm starting to understand the multi-layer a bit more.


      emWin can do 'software layers' to do multiple layers virtually, but have to specifically set that up..

      Please correct me if I'm wrong, but I think I see what's going on.. the example Iwas looking at was the ''TemperatureControl'' example from the Segger site directly, it was using 3 layers, but I see now.

      it's a WIN32 example... make sense :)