What do you want to achieve?
I’m using LVGL v9 for a little windows utility. I implemented WindowProc successfully and I got everything running except PRESS_LOST in button logic for when a button is pushed but then cancelled by moving the cursor away from the button.
For the titlebar close button I can successfully get the PRESS_LOST event to fire but the button remains in limbo. I need to click any button twice after to reset the button states and make them work again. How do I properly reset the button states?
One additional tidbit… if i move the cursor over ‘cont’ and release it will reset the button states as expected.
For the select button in my content widget (cont) I cannot get PRESS_LOST to fire and the click will be executed no matter where on screen I release the press.
What have you tried so far?
Too many to list and I have too little inner knowledge of LVGL to figure this out in a reasonable time.
Code to reproduce
The following is the LVGL code only. Adding the WindowProc code is might be overcomplicate things since a lot would need additional explanation.
lv_obj_t* btn_close = nullptr;
lv_obj_t* win = nullptr;
lv_obj_t* cont = nullptr;
lv_obj_t* debug_txt = nullptr;
static void select_button_handler(lv_event_t * e) {
lv_event_code_t code = lv_event_get_code(e);
if (code == LV_EVENT_PRESSED) {
if (g_hwnd) {
SetCapture(g_hwnd);
}
}
else if (code == LV_EVENT_PRESS_LOST) {
ReleaseCapture();
if (debug_txt) {
lv_textarea_add_text(debug_txt, "SELECT PRESS_LOSS!\n");
}
}
else if (code == LV_EVENT_RELEASED) {
ReleaseCapture();
}
else if (code == LV_EVENT_CLICKED) {
std::string selectedFolder = SelectFolderDialog(g_hwnd);
if (!selectedFolder.empty() && txt_loc != NULL) {
lv_textarea_set_text(txt_loc, selectedFolder.c_str());
}
}
}
static void close_button_handler(lv_event_t * e) {
lv_event_code_t code = lv_event_get_code(e);
// lv_obj_t* btn = (lv_obj_t*)lv_event_get_target(e);
if (code == LV_EVENT_PRESSED) {
if (g_hwnd) {
SetCapture(g_hwnd);
}
}
else if (code == LV_EVENT_PRESS_LOST) {
ReleaseCapture();
if (debug_txt) {
lv_textarea_add_text(debug_txt, "CLOSE PRESS_LOSS!\n");
}
}
else if (code == LV_EVENT_RELEASED) {
ReleaseCapture();
}
else if (code == LV_EVENT_CLICKED) {
if (g_hwnd) {
ReleaseCapture();
PostMessage(g_hwnd, WM_CLOSE, 0, 0);
}
}
}
void lv_my_test_gui(void)
{
win = lv_win_create(lv_screen_active());
lv_obj_set_style_border_width(win, 1, LV_PART_MAIN);
lv_obj_set_scroll_dir(win, LV_DIR_NONE);
lv_win_add_title(win, "LVGL Test Window");
lv_obj_t * header = lv_win_get_header(win);
lv_obj_set_height(header, 36);
lv_obj_set_style_pad_all(header, 0, 4);
lv_obj_set_scroll_dir(header, LV_DIR_NONE);
btn_close = lv_win_add_button(win, LV_SYMBOL_CLOSE, 28);
lv_obj_set_size(btn_close, 28, 28);
lv_obj_set_style_shadow_width(btn_close, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_shadow_opa(btn_close, LV_OPA_TRANSP, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_clear_flag(btn_close, LV_OBJ_FLAG_PRESS_LOCK);
lv_obj_add_event_cb(btn_close, close_button_handler, LV_EVENT_PRESSED, NULL);
lv_obj_add_event_cb(btn_close, close_button_handler, LV_EVENT_RELEASED, NULL);
lv_obj_add_event_cb(btn_close, close_button_handler, LV_EVENT_PRESS_LOST, NULL);
lv_obj_add_event_cb(btn_close, close_button_handler, LV_EVENT_CLICKED, NULL);
cont = lv_win_get_content(win);
lv_obj_set_size(cont, LV_PCT(100), LV_PCT(100));
lv_obj_clear_flag(cont, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_style_border_width(cont, 0, LV_PART_MAIN);
lv_obj_set_style_radius(cont, 0, LV_PART_MAIN);
lv_obj_set_style_bg_color(cont, lv_color_hex(0xADD8E6), LV_PART_MAIN);
// Setup flex layout
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
lv_obj_set_style_pad_all(cont, 10, 0);
lv_obj_set_style_pad_row(cont, 5, 0);
// --- Location Row ---
lv_obj_t *row2 = lv_obj_create(cont);
lv_obj_set_size(row2, LV_PCT(100), 40);
lv_obj_set_flex_flow(row2, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(row2, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START);
lv_obj_set_style_pad_column(row2, 10, 0);
lv_obj_set_style_bg_opa(row2, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(row2, 0, 0);
lv_obj_set_style_pad_all(row2, 0, 0);
lv_obj_t *btn_select = lv_button_create(row2);
lv_obj_set_size(btn_select, 90, 28);
lv_obj_set_style_shadow_width(btn_select, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_shadow_opa(btn_select, LV_OPA_TRANSP, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_t *lbl_sel = lv_label_create(btn_select);
lv_label_set_text(lbl_sel, "Select");
lv_obj_center(lbl_sel);
lv_obj_add_event_cb(btn_select, select_button_handler, LV_EVENT_PRESSED, NULL);
lv_obj_add_event_cb(btn_select, select_button_handler, LV_EVENT_RELEASED, NULL);
lv_obj_add_event_cb(btn_select, select_button_handler, LV_EVENT_PRESS_LOST, NULL);
lv_obj_add_event_cb(btn_select, select_button_handler, LV_EVENT_CLICKED, NULL);
// --- Debug Text (separate, not in flex row) ---
debug_txt = lv_textarea_create(cont);
lv_obj_set_size(debug_txt, LV_PCT(100), 300);
lv_textarea_set_text(debug_txt, "Debug: No input yet\n");
}
Screenshot

Environment
- Win10:
- LVGL version: v9.3