Disabling keys in a messagebox doesnt work

What do you want to achieve?

After i press the yes or no key in a messagebox, i need these keys to be disabled.

What have you tried so far?

lv_obj_t *ftr = lv_msgbox_get_footer(mbox);
lv_obj_add_state(ftr, LV_STATE_DISABLED);

Code to reproduce

/*OK key callback*/
void btn100DensOK_cb(lv_event_t *e) 
{
  lv_obj_t *mbox = (lv_obj_t *)lv_event_get_user_data(e);

  lv_obj_t *obj = lv_msgbox_get_content(mbox);
   lv_obj_t *label = lv_obj_get_child(obj, 0);
  lv_label_set_text(label, "\n\nWait....");

  lv_obj_t *ftr = lv_msgbox_get_footer(mbox);
  lv_obj_add_state(ftr, LV_STATE_DISABLED);

  msgbox2close = mbox;
  set100Tmout = MBOX_TMOUT;

  return;
}
//==============================================

Screenshot and/or video

Environment

  • MCU/MPU/Board: ESP32S3
  • LVGL version: See lv_version.h 9.4

I have a messagebox where when i press ok, i have a delay before it closes (MBOX_TMOUT aboxe).
I need the ok/cancel keys to be disabled during this time.
I am passing the messagebox to the keys callback, then doing this:

lv_obj_t *ftr = lv_msgbox_get_footer(mbox);
lv_obj_add_state(ftr, LV_STATE_DISABLED);

but it doesnt disable the keys.
Why is this ?
How can I acheive this ?

Thanks,
–Royce

You could try maybe getting the children of the message box footer and disable them.

    // Get footer and disable its buttons
    lv_obj_t *ftr = lv_msgbox_get_footer(mbox);
    if(ftr) {
        uint32_t i;
        uint32_t child_cnt = lv_obj_get_child_count(ftr);
        for(i = 0; i < child_cnt; i++) {
            lv_obj_t *btn = lv_obj_get_child(ftr, i);
            lv_obj_add_state(btn, LV_STATE_DISABLED);
        }
    }

Can you check if this works for you?

Yes this works.
Thank you!
Logically my code should work too (disabling the parent(footer) should disable all children(buttons).
Could it be a bug ?

I checked the internals of lv_obj_add_state: lvgl/src/core/lv_obj.c at master · lvgl/lvgl · GitHub

void lv_obj_add_state(lv_obj_t * obj, lv_state_t state)
{
    LV_ASSERT_OBJ(obj, MY_CLASS);

    lv_state_t new_state = obj->state | state;
    if(obj->state != new_state) {
        update_obj_state(obj, new_state);
        if(lv_obj_has_flag(obj, LV_OBJ_FLAG_STATE_TRICKLE)) {
            lv_obj_children_add_state(obj, state);
        }
    }
}

If the parent, in this case the message box, has the flag LV_OBJ_FLAG_STATE_TRICKLE, state changes should propagate to children as well.

So probably this is a better solution than my previous one. It is more the “LVGL way” of handling it.

1 Like