Lv_msgbox_create

Hi everyone, I’m trying to use lv_msgbox_create passing the texts textos[19] to be displayed in a variable ec_text, but it doesn’t work. Can you help me? Thank you.

lvgl Versión 3.8.5

const char *textos[19];
char *ec_text;

ec_text = textos[13];
Config_mbox1 = lv_msgbox_create(Configurar, ec_text, ec_text, NULL, true);

Sorry, I don’t see any string which should be displayed.
Your pointer array textos[19] doesn’t contain any pointers to strings.

Hello, sorry that it was so schematic, I am attaching a more complete detail of the program. When I use it in the lv_msgbox_create it doesn’t work, it sends unreadable data, but when I use it in the lv_label_create, yes.
Greetings.

const char *textos[19] = { "Ahora",  "Mejor hoy",  "Datos proporcionados",  "Ha conectado a",  "Sin conesion a",  "SSID Wifi:",  "Contraseña",  "Nombre red wifi",  "Contraseña red wifi",  "Pais:",  "Idioma",  "Guardar",  "AVISO", "ERROR", "Registro Wifi OK.",  "Registro rechazado.",  "Ambos campos obligatorios.", "GBR\nESP", "ENG\nSPA" };
char *ec_text;

void event_cb(lv_event_t * e) {
   lv_obj_t * obj = lv_event_get_current_target(e);
   int boton = lv_msgbox_get_active_btn(obj);
   lv_msgbox_close(ui_Config_mbox0);
   if ( boton == 0) {
     if ( !ec_ssid == 0 & !ec_pass == 0 ) { 
       Wifi_On = escribir_EEPROM(ec_ssid, ec_pass, w_pais, w_idioma);
       if (Wifi_On == 1) {
         ec_text = textos[14];
         Config_mbox1 = lv_msgbox_create(Configurar, "AVISO", ec_text, NULL, true);
         lv_obj_align(Config_mbox1, LV_ALIGN_CENTER, 0, 0);
       } else {
         ec_text = textos[15];
         Config_mbox1 = lv_msgbox_create(Configurar, "ERROR", ec_text, NULL, true);
         lv_obj_align(Config_mbox1, LV_ALIGN_CENTER, 0, 0);       
       }
     } else {
       if  (!ec_ssid == 0 || !ec_pass == 0) {
         ec_text = textos[13];
         Config_mbox1 = lv_msgbox_create(Configurar, "ERROR", ec_text, NULL, true);
         lv_obj_align(ui_Config_mbox1, LV_ALIGN_CENTER, 0, 0);
       }
     }          
   }
}


void Configurar_screen_init(void) {
   Configurar = lv_obj_create(NULL);
   lv_obj_clear_flag(Configurar, LV_OBJ_FLAG_SCROLLABLE);

   Config_Label2 = lv_label_create(Configurar);
   lv_obj_set_width(Config_Label2, LV_SIZE_CONTENT);
   lv_obj_set_height(Config_Label2, LV_SIZE_CONTENT);
   lv_obj_set_x(Config_Label2, -96);
   lv_obj_set_y(Config_Label2, -59);
   lv_obj_set_align(Config_Label2, LV_ALIGN_CENTER);
   ec_text = textos[5];
   lv_label_set_text(Config_Label2, ec_text);   //"SSID Wifi:"
}

You are sure that event_cb is called?

The only obvious mistake is in the line:

if ( !ec_ssid == 0 & !ec_pass == 0 ) { 

I think you forget the second ‘&’:
Shouldn’t it be:

if ( !ec_ssid == 0 && !ec_pass == 0 ) { 

And a little bit confusing:
You use the ‘!’ in front of ec_ssid and ec_pass and you are checking for == 0.

You should always use explicit parenthesis around expressions. That makes it clear what someone wants:
E.g

if (!(ec_ssid == 0) && !(ec_pass == 0)). 

Or better readable/understandable:

if ((ec_ssid != 0) && (ec_pass != 0))

It sure does. The program shows the Lv-msgbox, the only thing is that the text does not display it well. If I change the instruction to: ec_text = “TEST”; instead of ec_text = textos[13]; it works correctly and the Lv_msgbox shows TEST.

Strange, it looks like your array textos is cleared!?

Pero, cuando la uso la misma en lv_label si funciona.

Sorry. But, when I use the same in lv_label it works.

Configurar_screen_init is called at the very beginning?
And when is event_cb called? Later?
Maybe there is something wrong in-between? Just a guess.

You’re right. I have used printf to print the value of texts[13] to the console and when it is in Configure_screen_init it shows the correct value, but when it is in event_cb it shows / �0 �?� �?4��?
But, I check the program and I don’t find anything strange. Do you have any idea how to find the problem? Thank you.

After doing a lot of tests, I have come to the conclusion that when using global variables with pointers in lv_event these get corrupted and against my principles, I loaded the texts inside the program instructions with if (idiom).

I think there is a problem, and taking a different approach doesn’t mean that the basic problem is fixed.
You are just not seeing it any more.

You have the const char* textos in the global scope? Outside of any function, right?
The array textos is reserved (within RAM) for holding the pointers to the string (which are located in ROM).
The data within the array should not change without any reason. The code you posted has only read access to it.
There must be something which is changing it.

If there is something which is strange try to figure out the reason. Either it will help you to understand that you misinterpreted something or you did something wrong.
Just doing a work-around will catch up with you later.

I have found this:
lv_obj_add_event_cb(obj, event_Set_Button1, LV_EVENT_CLICKED, &num1);
and I have substituted &num1 for texts[19] and at first it compiles, but then in void event_Configurar_Button1(lv_event_t * e) {} I don’t know how to retrieve texts[19]. Could you help me?

would this also work syntactically?? Not a huge C guy but I know this type of expression does work in other programming languages.

if (ec_ssid != 0 != ec_pass )

Syntactically? Yes. At least it compiles just with a
warning: suggest parentheses around comparison in operand of '!='

Although I assume this would correctly work, I would never recommend writing it in this way.
I do not remember ever seen such an expression.

All expressions which needs a second, third (or more) look at it, trying to understand what an expression does are bad.
Don’t put too much into one line. Write clear, readable and understandable code. Let the compiler do the optimizations.

Another argument against such a construct (I did not try it, but I think I’m right) is the following example:

if (ec_ssid != 4 != ec_pass)

This would not work in the (possible) intended way:
One comparison is int to int and the next comparison is bool to bool (I assume).

There are rules in C about the order of resolving exprssions and precedence of operators. But do you have it always on mind?

And I would not recommend such a construct in any other programming language for the same reasons.

JM2C

That kind of an expression is usually used when doing a greater than and less than operation.

An example would be if hit testing an LVGL object for cursor or touch. This is written in python but easily changed to c code

x1 = obj.get_x()
y1 = obj.get_y()

x2 = x1 + obj.get_width()
y2 = y1 + obj.get_height()


x, y = some_touch_input()

if x1 <= x <= x2 and y1 <= y <= y2:
   print('got a hit')

could also be written

if x1 <= x and x <= x2 and y1<= y and y <= y2:
   print('got a hit')

you also have

if [x1, y1] <= [x, y] and [x, y] <= [x2, y2]:
   print('got a hit')

yet another

if [x1, y1] <= [x, y] <= [x2, y2]:
   print('got a hit')

it’s called chained comparison. I just didn’t know if C code supported it or not.

Ok, I see, python.
Do be honest, I didn’t know that python has a “chained comparison”.

Whereas your example with the x1 <= x <= x2 is more obvious and intuitive than in the previous one (as I think).

The interesting thing: What does python when I would use parenthesis? Outputs an error? As the result from one comparison is an boolean and the second would compare to a number?

Hello, looking at the Lvgl manual I have found a possible user data pass through the last parameter of lv_obj_add_event_cb:

lv_obj_add_event_cb(Config_Button1, event_Config_Button1, LV_EVENT_CLICKED, &textos);
void event_Config_Button1(lv_event_t * e) {
    lv_event_code_t event_code = lv_event_get_code(e);
    lv_obj_t * target = lv_event_get_target(e);
    lv_obj_t *Qtextos = lv_event_get_user_data(e);
    printf( "textos = %sn", Qtextos);
    if(event_code == LV_EVENT_CLICKED) {
      static const char * btns[] = {"Ok", "No", ""};
      ec_text = "qqq";
      Config_mbox0 = lv_msgbox_create(NULL, "Process in progress", ec_text , btns, true); 
      lv_obj_align(Config_mbox0, LV_ALIGN_CENTER, 0, 0);
      lv_obj_add_event_cb(Config_mbox0,event_cb, LV_EVENT_VALUE_CHANGED, NULL);                              
    }
}
´´´´´
And by console in the printf output:
textos = l�?p�?}�?��?�?�?"�?-�??�?U�?^�?e�?j�?q�?w�?��?��?��?��?n
Something comes, but I don't know how to deal with it. You can help. thank you.

Your mistake is here:

lv_obj_t *Qtextos = lv_event_get_user_data(e);

It should be

char**  paTextos = lv_event_get_user_data (e);

printf ("textos = %s\n", paTextos[0]);

Some explanations:
Your call of

lv_obj_add_event_cb(Config_Button1, event_Config_Button1, LV_EVENT_CLICKED, &textos);

passes the start address of the array which holds the addresses of the strings (char*)
When reading the event user data, you should assign it to a variable of type char** (a pointer to pointer of char).
Now you can acces the single strings with paTextos[0…18].

Your printf( "textos = %sn", Qtextos); prints out the array of pointers (which is binary data and not any char string),
and not the strings itself.
For this you only see rubbish. In addition I think, you forget the '' in front of the last n within your printf string.

When you take a look at one of your previous posts, you had something equivalent:

correct value, but when it is in event_cb it shows / �0 �?� �?4��?

I have modified it as you indicate and it continues to appear rubbish:
textos = ?

void event_Config_Button1(lv_event_t * e) {
   lv_event_code_t event_code = lv_event_get_code(e);
   lv_obj_t * target = lv_event_get_target(e);
   
   char** Qtextos = lv_event_get_user_data(e);
   printf( "textos = %s\n", Qtextos[14]);
   if(event_code == LV_EVENT_CLICKED) {
     static const char * btns[] = {"Ok", "No", ""};
     ec_text = Qtextos[14];
     Config_mbox0 = lv_msgbox_create(NULL, "Process in progress", ec_text , btns, true); //
     lv_obj_align(Config_mbox0, LV_ALIGN_CENTER, 0, 0);
     lv_obj_add_event_cb(Config_mbox0, event_cb, LV_EVENT_VALUE_CHANGED, NULL);                              
   }
}
````