feat(ui): 统一管理IUP控件名称常量,增强可维护性

refactor(core): 移除未使用的get_app_context函数
refactor(os_env): 修改backup_registry函数以返回错误码并备份到指定目录
refactor(path_manager): 增强路径管理函数的错误处理
This commit is contained in:
2026-04-28 21:01:52 +08:00
parent 86792012e2
commit ea3d678d22
11 changed files with 229 additions and 178 deletions
-4
View File
@@ -2,7 +2,6 @@
#define APP_CONTEXT_H
#include "utils/string_ext.h"
#include <iup.h>
// 应用上下文结构体,用于存储应用运行时的状态
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
+7
View File
@@ -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
+2 -1
View File
@@ -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);
+3 -1
View File
@@ -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
+38
View File
@@ -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
+34 -27
View File
@@ -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"));
}
-11
View File
@@ -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");
}
+12 -6
View File
@@ -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;
+18 -33
View File
@@ -5,7 +5,16 @@
#include <wchar.h>
#include <libintl.h>
#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);
+44 -66
View File
@@ -2,6 +2,7 @@
#include "controller/callbacks.h"
#include "core/lua_config.h"
#include "utils/i18n.h"
#include "utils/ui_constants.h"
#include <stddef.h>
#include <string.h>
@@ -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"));
}
+71 -29
View File
@@ -5,6 +5,7 @@
#include <stdlib.h>
#include <time.h>
#include <direct.h>
#include <shlobj.h>
// 检查管理员权限
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;
}