diff --git a/include/core/app_context.h b/include/core/app_context.h index c77beee..847c632 100644 --- a/include/core/app_context.h +++ b/include/core/app_context.h @@ -2,7 +2,6 @@ #define APP_CONTEXT_H #include "utils/string_ext.h" -#include // 应用上下文结构体,用于存储应用运行时的状态 typedef struct { @@ -16,7 +15,4 @@ AppContext* create_app_context(void); // 销毁应用上下文 void destroy_app_context(AppContext* ctx); -// 获取应用上下文 -AppContext* get_app_context(Ihandle *ih); - #endif // APP_CONTEXT_H diff --git a/include/ui/ui_utils.h b/include/ui/ui_utils.h index edaebbe..9b57c4e 100644 --- a/include/ui/ui_utils.h +++ b/include/ui/ui_utils.h @@ -5,9 +5,16 @@ #include "utils/string_ext.h" // 刷新单个列表框样式 +// 功能说明: +// 1. 路径有效性检查:无效路径显示红色前景色 (255 0 0) +// 2. 重复检查:重复路径显示橙色前景色 (255 128 0),只检查当前项之前的项 +// 3. 斑马纹背景:奇偶行交替显示不同背景色 (白/灰) +// 注意: 该函数需要IUP控件已设置NAME属性 void refresh_single_list_style(Ihandle *list); // 同步字符串列表到 UI 列表框 +// 将StringList中的所有项同步到IUP FlatList控件中 +// 会先清空列表然后重新添加所有项,最后刷新样式 void sync_string_list_to_ui(Ihandle *list_ui, const StringList *str_list); #endif // UI_UTILS_H diff --git a/include/utils/error_code.h b/include/utils/error_code.h index 1d0bc79..cc9cf85 100644 --- a/include/utils/error_code.h +++ b/include/utils/error_code.h @@ -11,7 +11,8 @@ typedef enum { ERR_INVALID_FORMAT = -6, // 无效格式 ERR_REGISTRY_FAILED = -7, // 注册表操作失败 ERR_NOT_FOUND = -8, // 未找到 - ERR_EXISTS = -9 // 已存在 + ERR_EXISTS = -9, // 已存在 + ERR_INVALID_INDEX = -10 // 无效索引 } ErrorCode; const char* error_code_to_string(ErrorCode code); diff --git a/include/utils/os_env.h b/include/utils/os_env.h index 039f892..fd7e90e 100644 --- a/include/utils/os_env.h +++ b/include/utils/os_env.h @@ -1,6 +1,8 @@ #ifndef OS_ENV_H #define OS_ENV_H +#include "utils/error_code.h" + // 检查是否以管理员权限运行 int check_admin(void); @@ -8,6 +10,6 @@ int check_admin(void); int is_path_valid(const char *path); // 备份注册表 -void backup_registry(void); +ErrorCode backup_registry(void); #endif // OS_ENV_H diff --git a/include/utils/ui_constants.h b/include/utils/ui_constants.h new file mode 100644 index 0000000..b34ed9e --- /dev/null +++ b/include/utils/ui_constants.h @@ -0,0 +1,38 @@ +#ifndef UI_CONSTANTS_H +#define UI_CONSTANTS_H + +// 缓冲区大小常量 +#define PATH_BUFFER_SIZE 4096 + +// 控件名称常量 - 统一管理所有IUP控件名称字符串 +// 使用这些常量替代硬编码字符串,便于维护和减少拼写错误 + +// 列表控件 +#define CTRL_LIST_SYS "LIST_SYS" +#define CTRL_LIST_USER "LIST_USER" + +// 选项卡 +#define CTRL_TABS_MAIN "TABS_MAIN" + +// 搜索框 +#define CTRL_TXT_SEARCH "TXT_SEARCH" + +// 状态标签 +#define CTRL_LBL_STATUS "LBL_STATUS" + +// 操作按钮 +#define CTRL_BTN_NEW "BTN_NEW" +#define CTRL_BTN_EDIT "BTN_EDIT" +#define CTRL_BTN_BROWSE "BTN_BROWSE" +#define CTRL_BTN_DEL "BTN_DEL" +#define CTRL_BTN_UP "BTN_UP" +#define CTRL_BTN_DOWN "BTN_DOWN" +#define CTRL_BTN_CLEAN "BTN_CLEAN" +#define CTRL_BTN_IMPORT "BTN_IMPORT" +#define CTRL_BTN_EXPORT "BTN_EXPORT" +#define CTRL_BTN_OK "BTN_OK" +#define CTRL_BTN_CANCEL "BTN_CANCEL" +#define CTRL_BTN_HELP "BTN_HELP" +#define CTRL_BTN_LANG "BTN_LANG" + +#endif // UI_CONSTANTS_H diff --git a/src/controller/callbacks.c b/src/controller/callbacks.c index 6f8849c..7a2026d 100644 --- a/src/controller/callbacks.c +++ b/src/controller/callbacks.c @@ -10,6 +10,7 @@ #include "utils/safe_string.h" #include "utils/logger.h" #include "utils/i18n.h" +#include "utils/ui_constants.h" #include "ui/ui_utils.h" #include "ui/dialogs.h" #include "ui/main_window.h" @@ -21,19 +22,25 @@ // 辅助函数:获取主对话框 static Ihandle *get_main_dlg() { - // 在实际情况中,可以通过 IupGetHandle 注册名字,或者通过某个全局/静态缓存 - // 但如果想彻底不用全局,我们可以在 IupSetHandle 里面把主窗口存下来 return IupGetHandle("MAIN_DIALOG"); } +// 辅助函数:从对话框获取应用上下文(core层不依赖IUP,因此在此实现) +static AppContext *get_app_context_from_dlg(Ihandle *dlg) +{ + if (!dlg) + return NULL; + return (AppContext *)IupGetAttribute(dlg, "APP_CONTEXT"); +} + // 获取当前的缓存数据列表 static StringList *get_current_raw_data(Ihandle *dlg) { - AppContext *ctx = get_app_context(dlg); + AppContext *ctx = get_app_context_from_dlg(dlg); if (!ctx) return NULL; - Ihandle *tabs_main = IupGetDialogChild(dlg, "TABS_MAIN"); + Ihandle *tabs_main = IupGetDialogChild(dlg, CTRL_TABS_MAIN); int pos = IupGetInt(tabs_main, "VALUEPOS"); if (pos == 0) return &ctx->sys_paths; @@ -45,20 +52,20 @@ static StringList *get_current_raw_data(Ihandle *dlg) // 辅助函数:获取当前选中的列表UI控件 static Ihandle *get_current_list(Ihandle *dlg) { - Ihandle *tabs_main = IupGetDialogChild(dlg, "TABS_MAIN"); + Ihandle *tabs_main = IupGetDialogChild(dlg, CTRL_TABS_MAIN); int pos = IupGetInt(tabs_main, "VALUEPOS"); if (pos == 0) - return IupGetDialogChild(dlg, "LIST_SYS"); + return IupGetDialogChild(dlg, CTRL_LIST_SYS); if (pos == 1) - return IupGetDialogChild(dlg, "LIST_USER"); - return IupGetDialogChild(dlg, "LIST_SYS"); + return IupGetDialogChild(dlg, CTRL_LIST_USER); + return IupGetDialogChild(dlg, CTRL_LIST_SYS); } // 按钮回调:新建 int btn_new_cb(Ihandle *self) { Ihandle *dlg = IupGetDialog(self); - char buffer[1024] = ""; + char buffer[PATH_BUFFER_SIZE] = ""; if (custom_input_dialog("新建环境变量", "请输入路径:", buffer, sizeof(buffer))) { if (strlen(buffer) > 0) @@ -89,7 +96,7 @@ int btn_edit_cb(Ihandle *self) if (selected - 1 >= raw_data->count) return IUP_DEFAULT; - char buffer[4096]; + char buffer[PATH_BUFFER_SIZE]; safe_strcpy(buffer, sizeof(buffer), raw_data->items[selected - 1]); if (custom_input_dialog("编辑环境变量", "编辑路径:", buffer, sizeof(buffer))) @@ -168,7 +175,7 @@ int btn_del_cb(Ihandle *self) sync_string_list_to_ui(current_list, raw_data); - Ihandle *lbl_status = IupGetDialogChild(dlg, "LBL_STATUS"); + Ihandle *lbl_status = IupGetDialogChild(dlg, CTRL_LBL_STATUS); if (lbl_status) IupSetAttribute(lbl_status, "TITLE", lua_config_get_string("status", "deleted")); @@ -280,14 +287,14 @@ int list_dropfiles_cb(Ihandle *self, const char *filename, int num, int x, int y { Ihandle *dlg = IupGetDialog(self); Ihandle *current_list = self; - AppContext *ctx = get_app_context(dlg); + AppContext *ctx = get_app_context_from_dlg(dlg); if (!ctx) return IUP_DEFAULT; StringList *raw_data = NULL; - if (self == IupGetDialogChild(dlg, "LIST_SYS")) + if (self == IupGetDialogChild(dlg, CTRL_LIST_SYS)) raw_data = &ctx->sys_paths; - else if (self == IupGetDialogChild(dlg, "LIST_USER")) + else if (self == IupGetDialogChild(dlg, CTRL_LIST_USER)) raw_data = &ctx->user_paths; else return IUP_DEFAULT; @@ -295,7 +302,7 @@ int list_dropfiles_cb(Ihandle *self, const char *filename, int num, int x, int y DWORD attr = GetFileAttributesA(filename); if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY)) { - Ihandle *txt_search = IupGetDialogChild(dlg, "TXT_SEARCH"); + Ihandle *txt_search = IupGetDialogChild(dlg, CTRL_TXT_SEARCH); if (txt_search) IupSetAttribute(txt_search, "VALUE", ""); @@ -306,7 +313,7 @@ int list_dropfiles_cb(Ihandle *self, const char *filename, int num, int x, int y } else { - Ihandle *lbl_status = IupGetDialogChild(dlg, "LBL_STATUS"); + Ihandle *lbl_status = IupGetDialogChild(dlg, CTRL_LBL_STATUS); if (lbl_status) IupSetAttribute(lbl_status, "TITLE", lua_config_get_string("status", "drag_folder_only")); } @@ -329,7 +336,7 @@ int list_k_any_cb(Ihandle *self, int c) int btn_ok_cb(Ihandle *self) { Ihandle *dlg = IupGetDialog(self); - AppContext *ctx = get_app_context(dlg); + AppContext *ctx = get_app_context_from_dlg(dlg); if (!ctx) return IUP_DEFAULT; @@ -344,7 +351,7 @@ int btn_ok_cb(Ihandle *self) ErrorCode sys_ok = save_system_paths(&ctx->sys_paths); ErrorCode user_ok = save_user_paths(&ctx->user_paths); - Ihandle *lbl_status = IupGetDialogChild(dlg, "LBL_STATUS"); + Ihandle *lbl_status = IupGetDialogChild(dlg, CTRL_LBL_STATUS); if (sys_ok == ERR_OK && user_ok == ERR_OK) { @@ -383,7 +390,7 @@ int btn_cancel_cb(Ihandle *self) int btn_import_cb(Ihandle *self) { Ihandle *dlg = IupGetDialog(self); - AppContext *ctx = get_app_context(dlg); + AppContext *ctx = get_app_context_from_dlg(dlg); if (!ctx) return IUP_DEFAULT; @@ -443,7 +450,7 @@ int btn_import_cb(Ihandle *self) { add_string_list(&ctx->sys_paths, imported.system.items[i]); } - Ihandle *list_sys = IupGetDialogChild(dlg, "LIST_SYS"); + Ihandle *list_sys = IupGetDialogChild(dlg, CTRL_LIST_SYS); sync_string_list_to_ui(list_sys, &ctx->sys_paths); total_imported += imported.system.count; } @@ -455,7 +462,7 @@ int btn_import_cb(Ihandle *self) { add_string_list(&ctx->user_paths, imported.user.items[i]); } - Ihandle *list_user = IupGetDialogChild(dlg, "LIST_USER"); + Ihandle *list_user = IupGetDialogChild(dlg, CTRL_LIST_USER); sync_string_list_to_ui(list_user, &ctx->user_paths); total_imported += imported.user.count; } @@ -464,7 +471,7 @@ int btn_import_cb(Ihandle *self) snprintf(msg, sizeof(msg), "成功导入 %d 个路径!", total_imported); IupMessage("导入成功", msg); - Ihandle *lbl_status = IupGetDialogChild(dlg, "LBL_STATUS"); + Ihandle *lbl_status = IupGetDialogChild(dlg, CTRL_LBL_STATUS); if (lbl_status) IupSetAttribute(lbl_status, "TITLE", lua_config_get_string("status", "loaded")); } @@ -483,7 +490,7 @@ int btn_import_cb(Ihandle *self) int btn_export_cb(Ihandle *self) { Ihandle *dlg = IupGetDialog(self); - AppContext *ctx = get_app_context(dlg); + AppContext *ctx = get_app_context_from_dlg(dlg); if (!ctx) return IUP_DEFAULT; @@ -545,7 +552,7 @@ void load_all_paths(void) Ihandle *dlg = get_main_dlg(); if (!dlg) return; - AppContext *ctx = get_app_context(dlg); + AppContext *ctx = get_app_context_from_dlg(dlg); if (!ctx) return; @@ -565,13 +572,13 @@ void load_all_paths(void) log_info("Loaded user paths: %d", ctx->user_paths.count); } - Ihandle *list_sys = IupGetDialogChild(dlg, "LIST_SYS"); - Ihandle *list_user = IupGetDialogChild(dlg, "LIST_USER"); + Ihandle *list_sys = IupGetDialogChild(dlg, CTRL_LIST_SYS); + Ihandle *list_user = IupGetDialogChild(dlg, CTRL_LIST_USER); sync_string_list_to_ui(list_sys, &ctx->sys_paths); sync_string_list_to_ui(list_user, &ctx->user_paths); - Ihandle *lbl_status = IupGetDialogChild(dlg, "LBL_STATUS"); + Ihandle *lbl_status = IupGetDialogChild(dlg, CTRL_LBL_STATUS); if (lbl_status) IupSetAttribute(lbl_status, "TITLE", lua_config_get_string("status", "loaded")); } diff --git a/src/core/app_context.c b/src/core/app_context.c index d2f0bd3..6e38b30 100644 --- a/src/core/app_context.c +++ b/src/core/app_context.c @@ -22,15 +22,4 @@ void destroy_app_context(AppContext *ctx) clear_string_list(&ctx->user_paths); free(ctx); } -} - -// 获取应用上下文 -AppContext *get_app_context(Ihandle *ih) -{ - if (!ih) - return NULL; - Ihandle *dlg = IupGetDialog(ih); - if (!dlg) - return NULL; - return (AppContext *)IupGetAttribute(dlg, "APP_CONTEXT"); } \ No newline at end of file diff --git a/src/core/path_manager.c b/src/core/path_manager.c index abaddd3..6df9a9f 100644 --- a/src/core/path_manager.c +++ b/src/core/path_manager.c @@ -8,9 +8,11 @@ // 删除指定索引的路径项 ErrorCode path_manager_remove_at(StringList *list, int index) { - if (!list || index < 0 || index >= list->count) + if (!list) return ERR_NULL_PTR; - + if (index < 0 || index >= list->count) + return ERR_INVALID_INDEX; + free(list->items[index]); for (int i = index; i < list->count - 1; i++) { @@ -24,9 +26,11 @@ ErrorCode path_manager_remove_at(StringList *list, int index) // 向上移动路径项 ErrorCode path_manager_move_up(StringList *list, int index) { - if (!list || index <= 0 || index >= list->count) + if (!list) return ERR_NULL_PTR; - + if (index <= 0 || index >= list->count) + return ERR_INVALID_INDEX; + char *temp = list->items[index]; list->items[index] = list->items[index - 1]; list->items[index - 1] = temp; @@ -36,9 +40,11 @@ ErrorCode path_manager_move_up(StringList *list, int index) // 向下移动路径项 ErrorCode path_manager_move_down(StringList *list, int index) { - if (!list || index < 0 || index >= list->count - 1) + if (!list) return ERR_NULL_PTR; - + if (index < 0 || index >= list->count - 1) + return ERR_INVALID_INDEX; + char *temp = list->items[index]; list->items[index] = list->items[index + 1]; list->items[index + 1] = temp; diff --git a/src/main.c b/src/main.c index 340acaa..fc3f77a 100644 --- a/src/main.c +++ b/src/main.c @@ -5,7 +5,16 @@ #include #include #include "core/app_context.h" +#include "utils/ui_constants.h" #include "core/lua_config.h" + +// 需要在非管理员模式禁用的按钮列表 +#define ADMIN_DISABLE_COUNT 10 +static const char* ADMIN_DISABLE_BUTTONS[] = { + CTRL_BTN_NEW, CTRL_BTN_EDIT, CTRL_BTN_BROWSE, CTRL_BTN_DEL, + CTRL_BTN_UP, CTRL_BTN_DOWN, CTRL_BTN_CLEAN, CTRL_BTN_OK, + CTRL_BTN_IMPORT, CTRL_BTN_EXPORT +}; #include "utils/string_ext.h" #include "utils/os_env.h" #include "utils/logger.h" @@ -98,42 +107,18 @@ int main(int argc, char **argv) { IupMessage(_("Warning"), _(lua_config_get_string("status", "admin_warning"))); - Ihandle *lbl_status = IupGetDialogChild(dlg, "LBL_STATUS"); + // 设置只读状态提示 + Ihandle *lbl_status = IupGetDialogChild(dlg, CTRL_LBL_STATUS); if (lbl_status) IupSetAttribute(lbl_status, "TITLE", _(lua_config_get_string("status", "readonly"))); - Ihandle *btn_new = IupGetDialogChild(dlg, "BTN_NEW"); - Ihandle *btn_edit = IupGetDialogChild(dlg, "BTN_EDIT"); - Ihandle *btn_browse = IupGetDialogChild(dlg, "BTN_BROWSE"); - Ihandle *btn_del = IupGetDialogChild(dlg, "BTN_DEL"); - Ihandle *btn_up = IupGetDialogChild(dlg, "BTN_UP"); - Ihandle *btn_down = IupGetDialogChild(dlg, "BTN_DOWN"); - Ihandle *btn_clean = IupGetDialogChild(dlg, "BTN_CLEAN"); - Ihandle *btn_ok = IupGetDialogChild(dlg, "BTN_OK"); - - if (btn_new) - IupSetAttribute(btn_new, "ACTIVE", "NO"); - if (btn_edit) - IupSetAttribute(btn_edit, "ACTIVE", "NO"); - if (btn_browse) - IupSetAttribute(btn_browse, "ACTIVE", "NO"); - if (btn_del) - IupSetAttribute(btn_del, "ACTIVE", "NO"); - if (btn_up) - IupSetAttribute(btn_up, "ACTIVE", "NO"); - if (btn_down) - IupSetAttribute(btn_down, "ACTIVE", "NO"); - if (btn_clean) - IupSetAttribute(btn_clean, "ACTIVE", "NO"); - if (btn_ok) - IupSetAttribute(btn_ok, "ACTIVE", "NO"); - - Ihandle *btn_import = IupGetDialogChild(dlg, "BTN_IMPORT"); - Ihandle *btn_export = IupGetDialogChild(dlg, "BTN_EXPORT"); - if (btn_import) - IupSetAttribute(btn_import, "ACTIVE", "NO"); - if (btn_export) - IupSetAttribute(btn_export, "ACTIVE", "NO"); + // 禁用所有需要管理员权限的按钮 + for (int i = 0; i < ADMIN_DISABLE_COUNT; i++) + { + Ihandle *btn = IupGetDialogChild(dlg, ADMIN_DISABLE_BUTTONS[i]); + if (btn) + IupSetAttribute(btn, "ACTIVE", "NO"); + } } IupShowXY(dlg, IUP_CENTER, IUP_CENTER); diff --git a/src/ui/main_window.c b/src/ui/main_window.c index bc3dfb8..02b3316 100644 --- a/src/ui/main_window.c +++ b/src/ui/main_window.c @@ -2,6 +2,7 @@ #include "controller/callbacks.h" #include "core/lua_config.h" #include "utils/i18n.h" +#include "utils/ui_constants.h" #include #include @@ -26,13 +27,13 @@ static Ihandle *create_path_list(const char *name) Ihandle *create_main_window(void) { // 创建系统路径列表 - Ihandle *list_sys = create_path_list("LIST_SYS"); + Ihandle *list_sys = create_path_list(CTRL_LIST_SYS); // 创建用户路径列表 - Ihandle *list_user = create_path_list("LIST_USER"); + Ihandle *list_user = create_path_list(CTRL_LIST_USER); // 创建搜索框 Ihandle *txt_search = IupText(NULL); - IupSetAttribute(txt_search, "NAME", "TXT_SEARCH"); + IupSetAttribute(txt_search, "NAME", CTRL_TXT_SEARCH); IupSetAttribute(txt_search, "EXPAND", "HORIZONTAL"); IupSetAttribute(txt_search, "CUEBANNER", lua_config_get_string("label", "search_placeholder")); IupSetCallback(txt_search, "VALUECHANGED_CB", (Icallback)txt_search_cb); @@ -42,42 +43,42 @@ Ihandle *create_main_window(void) IupVbox(list_sys, NULL), IupVbox(list_user, NULL), NULL); - IupSetAttribute(tabs_main, "NAME", "TABS_MAIN"); + IupSetAttribute(tabs_main, "NAME", CTRL_TABS_MAIN); IupSetAttribute(tabs_main, "TABTITLE0", _(lua_config_get_string("label", "tab_sys"))); IupSetAttribute(tabs_main, "TABTITLE1", _(lua_config_get_string("label", "tab_user"))); IupSetAttribute(tabs_main, "TABTYPE", "TOP"); // 创建操作按钮 Ihandle *btn_new = IupButton(_(lua_config_get_string("button", "new")), NULL); - IupSetAttribute(btn_new, "NAME", "BTN_NEW"); + IupSetAttribute(btn_new, "NAME", CTRL_BTN_NEW); Ihandle *btn_edit = IupButton(_(lua_config_get_string("button", "edit")), NULL); - IupSetAttribute(btn_edit, "NAME", "BTN_EDIT"); + IupSetAttribute(btn_edit, "NAME", CTRL_BTN_EDIT); Ihandle *btn_browse = IupButton(_(lua_config_get_string("button", "browse")), NULL); - IupSetAttribute(btn_browse, "NAME", "BTN_BROWSE"); + IupSetAttribute(btn_browse, "NAME", CTRL_BTN_BROWSE); Ihandle *btn_del = IupButton(_(lua_config_get_string("button", "del")), NULL); - IupSetAttribute(btn_del, "NAME", "BTN_DEL"); + IupSetAttribute(btn_del, "NAME", CTRL_BTN_DEL); Ihandle *btn_up = IupButton(_(lua_config_get_string("button", "up")), NULL); - IupSetAttribute(btn_up, "NAME", "BTN_UP"); + IupSetAttribute(btn_up, "NAME", CTRL_BTN_UP); Ihandle *btn_down = IupButton(_(lua_config_get_string("button", "down")), NULL); - IupSetAttribute(btn_down, "NAME", "BTN_DOWN"); + IupSetAttribute(btn_down, "NAME", CTRL_BTN_DOWN); Ihandle *btn_clean = IupButton(_(lua_config_get_string("button", "clean")), NULL); - IupSetAttribute(btn_clean, "NAME", "BTN_CLEAN"); + IupSetAttribute(btn_clean, "NAME", CTRL_BTN_CLEAN); Ihandle *btn_import = IupButton(_(lua_config_get_string("button", "import")), NULL); - IupSetAttribute(btn_import, "NAME", "BTN_IMPORT"); + IupSetAttribute(btn_import, "NAME", CTRL_BTN_IMPORT); Ihandle *btn_export = IupButton(_(lua_config_get_string("button", "export")), NULL); - IupSetAttribute(btn_export, "NAME", "BTN_EXPORT"); + IupSetAttribute(btn_export, "NAME", CTRL_BTN_EXPORT); // 创建语言切换按钮 Ihandle *btn_lang = IupButton(_("Language"), NULL); - IupSetAttribute(btn_lang, "NAME", "BTN_LANG"); + IupSetAttribute(btn_lang, "NAME", CTRL_BTN_LANG); IupSetCallback(btn_lang, "ACTION", (Icallback)btn_lang_cb); // 设置按钮回调 @@ -123,16 +124,16 @@ Ihandle *create_main_window(void) // 创建状态标签 Ihandle *lbl_status = IupLabel(lua_config_get_string("status", "normal")); - IupSetAttribute(lbl_status, "NAME", "LBL_STATUS"); + IupSetAttribute(lbl_status, "NAME", CTRL_LBL_STATUS); IupSetAttribute(lbl_status, "EXPAND", "HORIZONTAL"); // 创建底部按钮 Ihandle *btn_ok = IupButton(_(lua_config_get_string("button", "ok")), NULL); - IupSetAttribute(btn_ok, "NAME", "BTN_OK"); + IupSetAttribute(btn_ok, "NAME", CTRL_BTN_OK); Ihandle *btn_cancel = IupButton(_(lua_config_get_string("button", "cancel")), NULL); - IupSetAttribute(btn_cancel, "NAME", "BTN_CANCEL"); + IupSetAttribute(btn_cancel, "NAME", CTRL_BTN_CANCEL); Ihandle *btn_help = IupButton(_(lua_config_get_string("button", "help")), NULL); - IupSetAttribute(btn_help, "NAME", "BTN_HELP"); + IupSetAttribute(btn_help, "NAME", CTRL_BTN_HELP); // 设置底部按钮回调 IupSetCallback(btn_ok, "ACTION", (Icallback)btn_ok_cb); @@ -176,60 +177,37 @@ void refresh_main_window_ui(Ihandle *main_dlg) if (!main_dlg) return; + // 设置窗口标题 IupSetAttribute(main_dlg, "TITLE", _(lua_config_get_string("app", "name"))); + // 设置选项卡标题 IupSetAttribute(main_dlg, "TABTITLE0", _(lua_config_get_string("label", "tab_sys"))); IupSetAttribute(main_dlg, "TABTITLE1", _(lua_config_get_string("label", "tab_user"))); - Ihandle *btn = IupGetDialogChild(main_dlg, "BTN_NEW"); - if (btn) - IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "new"))); + // 辅助函数:设置子控件标题 + #define SET_CHILD_TITLE(btn_name, text_key) \ + do { \ + Ihandle *btn = IupGetDialogChild(main_dlg, btn_name); \ + if (btn) IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", text_key))); \ + } while(0) - btn = IupGetDialogChild(main_dlg, "BTN_EDIT"); - if (btn) - IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "edit"))); + SET_CHILD_TITLE(CTRL_BTN_NEW, "new"); + SET_CHILD_TITLE(CTRL_BTN_EDIT, "edit"); + SET_CHILD_TITLE(CTRL_BTN_BROWSE, "browse"); + SET_CHILD_TITLE(CTRL_BTN_DEL, "del"); + SET_CHILD_TITLE(CTRL_BTN_UP, "up"); + SET_CHILD_TITLE(CTRL_BTN_DOWN, "down"); + SET_CHILD_TITLE(CTRL_BTN_CLEAN, "clean"); + SET_CHILD_TITLE(CTRL_BTN_IMPORT, "import"); + SET_CHILD_TITLE(CTRL_BTN_EXPORT, "export"); + SET_CHILD_TITLE(CTRL_BTN_OK, "ok"); + SET_CHILD_TITLE(CTRL_BTN_CANCEL, "cancel"); + SET_CHILD_TITLE(CTRL_BTN_HELP, "help"); - btn = IupGetDialogChild(main_dlg, "BTN_BROWSE"); - if (btn) - IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "browse"))); + #undef SET_CHILD_TITLE - btn = IupGetDialogChild(main_dlg, "BTN_DEL"); - if (btn) - IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "del"))); - - btn = IupGetDialogChild(main_dlg, "BTN_UP"); - if (btn) - IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "up"))); - - btn = IupGetDialogChild(main_dlg, "BTN_DOWN"); - if (btn) - IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "down"))); - - btn = IupGetDialogChild(main_dlg, "BTN_CLEAN"); - if (btn) - IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "clean"))); - - btn = IupGetDialogChild(main_dlg, "BTN_IMPORT"); - if (btn) - IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "import"))); - - btn = IupGetDialogChild(main_dlg, "BTN_EXPORT"); - if (btn) - IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "export"))); - - btn = IupGetDialogChild(main_dlg, "BTN_LANG"); - if (btn) - IupSetAttribute(btn, "TITLE", _("Language")); - - btn = IupGetDialogChild(main_dlg, "BTN_OK"); - if (btn) - IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "ok"))); - - btn = IupGetDialogChild(main_dlg, "BTN_CANCEL"); - if (btn) - IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "cancel"))); - - btn = IupGetDialogChild(main_dlg, "BTN_HELP"); - if (btn) - IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "help"))); + // 语言切换按钮标题单独处理(不是从配置读取) + Ihandle *btn_lang = IupGetDialogChild(main_dlg, CTRL_BTN_LANG); + if (btn_lang) + IupSetAttribute(btn_lang, "TITLE", _("Language")); } \ No newline at end of file diff --git a/src/utils/os_env.c b/src/utils/os_env.c index ae5f55c..de032fb 100644 --- a/src/utils/os_env.c +++ b/src/utils/os_env.c @@ -5,6 +5,7 @@ #include #include #include +#include // 检查管理员权限 int check_admin(void) @@ -45,46 +46,87 @@ int is_path_valid(const char *path) } // 备份注册表 -void backup_registry(void) +// 备份到 %APPDATA%/PathEditor/backups/ 目录下 +ErrorCode backup_registry(void) { - // 创建 records 目录 - if (_mkdir("records") == -1) + // 获取 AppData 路径 + wchar_t appdata_path[MAX_PATH]; + if (SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, appdata_path) != S_OK) { - // 目录可能已存在,忽略错误 + return ERR_FAILED; } - // 获取当前时间 + // 创建备份目录 + wchar_t backup_dir[MAX_PATH]; + swprintf(backup_dir, MAX_PATH, L"%s\\PathEditor\\backups", appdata_path); + CreateDirectoryW(backup_dir, NULL); + + // 生成时间戳 time_t t = time(NULL); struct tm *tm_info = localtime(&t); - char time_str[64]; - strftime(time_str, sizeof(time_str), "%Y%m%d_%H%M%S", tm_info); + wchar_t timestamp[64]; + wcsftime(timestamp, sizeof(timestamp), L"%Y%m%d_%H%M%S", tm_info); // 构造备份文件名 - char filename[256]; - snprintf(filename, sizeof(filename), "records\\backup_%s.reg", time_str); + wchar_t backup_file[MAX_PATH]; + swprintf(backup_file, MAX_PATH, L"%s\\path_backup_%s.txt", backup_dir, timestamp); - // 构造 reg export 命令 - char full_cmd[1024]; - snprintf(full_cmd, sizeof(full_cmd), "reg.exe export \"HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\" \"%s\" /y", filename); + // 打开文件 + FILE *fp = _wfopen(backup_file, L"w, ccs=UTF-8"); + if (!fp) + return ERR_FAILED; - // 使用 CreateProcess 隐藏窗口执行 - STARTUPINFOA si; - PROCESS_INFORMATION pi; - memset(&si, 0, sizeof(si)); - si.cb = sizeof(si); - si.dwFlags = STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; // 隐藏窗口 - memset(&pi, 0, sizeof(pi)); + // 备份系统 PATH + HKEY hKey; + int success = 0; - if (CreateProcessA(NULL, full_cmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", + 0, KEY_READ, &hKey) == ERROR_SUCCESS) { - // 等待进程结束 - WaitForSingleObject(pi.hProcess, INFINITE); - - DWORD exit_code = 0; - GetExitCodeProcess(pi.hProcess, &exit_code); - - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); + DWORD type, size; + if (RegQueryValueExW(hKey, L"Path", NULL, &type, NULL, &size) == ERROR_SUCCESS) + { + wchar_t *buffer = (wchar_t *)malloc(size + 2); + if (buffer) + { + memset(buffer, 0, size + 2); + if (RegQueryValueExW(hKey, L"Path", NULL, &type, (LPBYTE)buffer, &size) == ERROR_SUCCESS) + { + fwprintf(fp, L"# System PATH Backup\n"); + fwprintf(fp, L"%s\n\n", buffer); + success = 1; + } + free(buffer); + } + } + RegCloseKey(hKey); } + + // 备份用户 PATH + if (RegOpenKeyExW(HKEY_CURRENT_USER, + L"Environment", + 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + DWORD type, size; + if (RegQueryValueExW(hKey, L"Path", NULL, &type, NULL, &size) == ERROR_SUCCESS) + { + wchar_t *buffer = (wchar_t *)malloc(size + 2); + if (buffer) + { + memset(buffer, 0, size + 2); + if (RegQueryValueExW(hKey, L"Path", NULL, &type, (LPBYTE)buffer, &size) == ERROR_SUCCESS) + { + fwprintf(fp, L"# User PATH Backup\n"); + fwprintf(fp, L"%s\n", buffer); + success = 1; + } + free(buffer); + } + } + RegCloseKey(hKey); + } + + fclose(fp); + return success ? ERR_OK : ERR_FAILED; } \ No newline at end of file