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 #define APP_CONTEXT_H
#include "utils/string_ext.h" #include "utils/string_ext.h"
#include <iup.h>
// 应用上下文结构体,用于存储应用运行时的状态 // 应用上下文结构体,用于存储应用运行时的状态
typedef struct { typedef struct {
@@ -16,7 +15,4 @@ AppContext* create_app_context(void);
// 销毁应用上下文 // 销毁应用上下文
void destroy_app_context(AppContext* ctx); void destroy_app_context(AppContext* ctx);
// 获取应用上下文
AppContext* get_app_context(Ihandle *ih);
#endif // APP_CONTEXT_H #endif // APP_CONTEXT_H
+7
View File
@@ -5,9 +5,16 @@
#include "utils/string_ext.h" #include "utils/string_ext.h"
// 刷新单个列表框样式 // 刷新单个列表框样式
// 功能说明:
// 1. 路径有效性检查:无效路径显示红色前景色 (255 0 0)
// 2. 重复检查:重复路径显示橙色前景色 (255 128 0),只检查当前项之前的项
// 3. 斑马纹背景:奇偶行交替显示不同背景色 (白/灰)
// 注意: 该函数需要IUP控件已设置NAME属性
void refresh_single_list_style(Ihandle *list); void refresh_single_list_style(Ihandle *list);
// 同步字符串列表到 UI 列表框 // 同步字符串列表到 UI 列表框
// 将StringList中的所有项同步到IUP FlatList控件中
// 会先清空列表然后重新添加所有项,最后刷新样式
void sync_string_list_to_ui(Ihandle *list_ui, const StringList *str_list); void sync_string_list_to_ui(Ihandle *list_ui, const StringList *str_list);
#endif // UI_UTILS_H #endif // UI_UTILS_H
+2 -1
View File
@@ -11,7 +11,8 @@ typedef enum {
ERR_INVALID_FORMAT = -6, // 无效格式 ERR_INVALID_FORMAT = -6, // 无效格式
ERR_REGISTRY_FAILED = -7, // 注册表操作失败 ERR_REGISTRY_FAILED = -7, // 注册表操作失败
ERR_NOT_FOUND = -8, // 未找到 ERR_NOT_FOUND = -8, // 未找到
ERR_EXISTS = -9 // 已存在 ERR_EXISTS = -9, // 已存在
ERR_INVALID_INDEX = -10 // 无效索引
} ErrorCode; } ErrorCode;
const char* error_code_to_string(ErrorCode code); const char* error_code_to_string(ErrorCode code);
+3 -1
View File
@@ -1,6 +1,8 @@
#ifndef OS_ENV_H #ifndef OS_ENV_H
#define OS_ENV_H #define OS_ENV_H
#include "utils/error_code.h"
// 检查是否以管理员权限运行 // 检查是否以管理员权限运行
int check_admin(void); int check_admin(void);
@@ -8,6 +10,6 @@ int check_admin(void);
int is_path_valid(const char *path); int is_path_valid(const char *path);
// 备份注册表 // 备份注册表
void backup_registry(void); ErrorCode backup_registry(void);
#endif // OS_ENV_H #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/safe_string.h"
#include "utils/logger.h" #include "utils/logger.h"
#include "utils/i18n.h" #include "utils/i18n.h"
#include "utils/ui_constants.h"
#include "ui/ui_utils.h" #include "ui/ui_utils.h"
#include "ui/dialogs.h" #include "ui/dialogs.h"
#include "ui/main_window.h" #include "ui/main_window.h"
@@ -21,19 +22,25 @@
// 辅助函数:获取主对话框 // 辅助函数:获取主对话框
static Ihandle *get_main_dlg() static Ihandle *get_main_dlg()
{ {
// 在实际情况中,可以通过 IupGetHandle 注册名字,或者通过某个全局/静态缓存
// 但如果想彻底不用全局,我们可以在 IupSetHandle 里面把主窗口存下来
return IupGetHandle("MAIN_DIALOG"); 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) static StringList *get_current_raw_data(Ihandle *dlg)
{ {
AppContext *ctx = get_app_context(dlg); AppContext *ctx = get_app_context_from_dlg(dlg);
if (!ctx) if (!ctx)
return NULL; return NULL;
Ihandle *tabs_main = IupGetDialogChild(dlg, "TABS_MAIN"); Ihandle *tabs_main = IupGetDialogChild(dlg, CTRL_TABS_MAIN);
int pos = IupGetInt(tabs_main, "VALUEPOS"); int pos = IupGetInt(tabs_main, "VALUEPOS");
if (pos == 0) if (pos == 0)
return &ctx->sys_paths; return &ctx->sys_paths;
@@ -45,20 +52,20 @@ static StringList *get_current_raw_data(Ihandle *dlg)
// 辅助函数:获取当前选中的列表UI控件 // 辅助函数:获取当前选中的列表UI控件
static Ihandle *get_current_list(Ihandle *dlg) 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"); int pos = IupGetInt(tabs_main, "VALUEPOS");
if (pos == 0) if (pos == 0)
return IupGetDialogChild(dlg, "LIST_SYS"); return IupGetDialogChild(dlg, CTRL_LIST_SYS);
if (pos == 1) if (pos == 1)
return IupGetDialogChild(dlg, "LIST_USER"); return IupGetDialogChild(dlg, CTRL_LIST_USER);
return IupGetDialogChild(dlg, "LIST_SYS"); return IupGetDialogChild(dlg, CTRL_LIST_SYS);
} }
// 按钮回调:新建 // 按钮回调:新建
int btn_new_cb(Ihandle *self) int btn_new_cb(Ihandle *self)
{ {
Ihandle *dlg = IupGetDialog(self); Ihandle *dlg = IupGetDialog(self);
char buffer[1024] = ""; char buffer[PATH_BUFFER_SIZE] = "";
if (custom_input_dialog("新建环境变量", "请输入路径:", buffer, sizeof(buffer))) if (custom_input_dialog("新建环境变量", "请输入路径:", buffer, sizeof(buffer)))
{ {
if (strlen(buffer) > 0) if (strlen(buffer) > 0)
@@ -89,7 +96,7 @@ int btn_edit_cb(Ihandle *self)
if (selected - 1 >= raw_data->count) if (selected - 1 >= raw_data->count)
return IUP_DEFAULT; return IUP_DEFAULT;
char buffer[4096]; char buffer[PATH_BUFFER_SIZE];
safe_strcpy(buffer, sizeof(buffer), raw_data->items[selected - 1]); safe_strcpy(buffer, sizeof(buffer), raw_data->items[selected - 1]);
if (custom_input_dialog("编辑环境变量", "编辑路径:", buffer, sizeof(buffer))) 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); 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) if (lbl_status)
IupSetAttribute(lbl_status, "TITLE", lua_config_get_string("status", "deleted")); 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 *dlg = IupGetDialog(self);
Ihandle *current_list = self; Ihandle *current_list = self;
AppContext *ctx = get_app_context(dlg); AppContext *ctx = get_app_context_from_dlg(dlg);
if (!ctx) if (!ctx)
return IUP_DEFAULT; return IUP_DEFAULT;
StringList *raw_data = NULL; StringList *raw_data = NULL;
if (self == IupGetDialogChild(dlg, "LIST_SYS")) if (self == IupGetDialogChild(dlg, CTRL_LIST_SYS))
raw_data = &ctx->sys_paths; 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; raw_data = &ctx->user_paths;
else else
return IUP_DEFAULT; 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); DWORD attr = GetFileAttributesA(filename);
if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY)) 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) if (txt_search)
IupSetAttribute(txt_search, "VALUE", ""); IupSetAttribute(txt_search, "VALUE", "");
@@ -306,7 +313,7 @@ int list_dropfiles_cb(Ihandle *self, const char *filename, int num, int x, int y
} }
else else
{ {
Ihandle *lbl_status = IupGetDialogChild(dlg, "LBL_STATUS"); Ihandle *lbl_status = IupGetDialogChild(dlg, CTRL_LBL_STATUS);
if (lbl_status) if (lbl_status)
IupSetAttribute(lbl_status, "TITLE", lua_config_get_string("status", "drag_folder_only")); 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) int btn_ok_cb(Ihandle *self)
{ {
Ihandle *dlg = IupGetDialog(self); Ihandle *dlg = IupGetDialog(self);
AppContext *ctx = get_app_context(dlg); AppContext *ctx = get_app_context_from_dlg(dlg);
if (!ctx) if (!ctx)
return IUP_DEFAULT; return IUP_DEFAULT;
@@ -344,7 +351,7 @@ int btn_ok_cb(Ihandle *self)
ErrorCode sys_ok = save_system_paths(&ctx->sys_paths); ErrorCode sys_ok = save_system_paths(&ctx->sys_paths);
ErrorCode user_ok = save_user_paths(&ctx->user_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) 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) int btn_import_cb(Ihandle *self)
{ {
Ihandle *dlg = IupGetDialog(self); Ihandle *dlg = IupGetDialog(self);
AppContext *ctx = get_app_context(dlg); AppContext *ctx = get_app_context_from_dlg(dlg);
if (!ctx) if (!ctx)
return IUP_DEFAULT; return IUP_DEFAULT;
@@ -443,7 +450,7 @@ int btn_import_cb(Ihandle *self)
{ {
add_string_list(&ctx->sys_paths, imported.system.items[i]); 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); sync_string_list_to_ui(list_sys, &ctx->sys_paths);
total_imported += imported.system.count; 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]); 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); sync_string_list_to_ui(list_user, &ctx->user_paths);
total_imported += imported.user.count; total_imported += imported.user.count;
} }
@@ -464,7 +471,7 @@ int btn_import_cb(Ihandle *self)
snprintf(msg, sizeof(msg), "成功导入 %d 个路径!", total_imported); snprintf(msg, sizeof(msg), "成功导入 %d 个路径!", total_imported);
IupMessage("导入成功", msg); IupMessage("导入成功", msg);
Ihandle *lbl_status = IupGetDialogChild(dlg, "LBL_STATUS"); Ihandle *lbl_status = IupGetDialogChild(dlg, CTRL_LBL_STATUS);
if (lbl_status) if (lbl_status)
IupSetAttribute(lbl_status, "TITLE", lua_config_get_string("status", "loaded")); 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) int btn_export_cb(Ihandle *self)
{ {
Ihandle *dlg = IupGetDialog(self); Ihandle *dlg = IupGetDialog(self);
AppContext *ctx = get_app_context(dlg); AppContext *ctx = get_app_context_from_dlg(dlg);
if (!ctx) if (!ctx)
return IUP_DEFAULT; return IUP_DEFAULT;
@@ -545,7 +552,7 @@ void load_all_paths(void)
Ihandle *dlg = get_main_dlg(); Ihandle *dlg = get_main_dlg();
if (!dlg) if (!dlg)
return; return;
AppContext *ctx = get_app_context(dlg); AppContext *ctx = get_app_context_from_dlg(dlg);
if (!ctx) if (!ctx)
return; return;
@@ -565,13 +572,13 @@ void load_all_paths(void)
log_info("Loaded user paths: %d", ctx->user_paths.count); log_info("Loaded user paths: %d", ctx->user_paths.count);
} }
Ihandle *list_sys = IupGetDialogChild(dlg, "LIST_SYS"); Ihandle *list_sys = IupGetDialogChild(dlg, CTRL_LIST_SYS);
Ihandle *list_user = IupGetDialogChild(dlg, "LIST_USER"); Ihandle *list_user = IupGetDialogChild(dlg, CTRL_LIST_USER);
sync_string_list_to_ui(list_sys, &ctx->sys_paths); sync_string_list_to_ui(list_sys, &ctx->sys_paths);
sync_string_list_to_ui(list_user, &ctx->user_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) if (lbl_status)
IupSetAttribute(lbl_status, "TITLE", lua_config_get_string("status", "loaded")); IupSetAttribute(lbl_status, "TITLE", lua_config_get_string("status", "loaded"));
} }
-11
View File
@@ -23,14 +23,3 @@ void destroy_app_context(AppContext *ctx)
free(ctx); 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");
}
+9 -3
View File
@@ -8,8 +8,10 @@
// 删除指定索引的路径项 // 删除指定索引的路径项
ErrorCode path_manager_remove_at(StringList *list, int index) ErrorCode path_manager_remove_at(StringList *list, int index)
{ {
if (!list || index < 0 || index >= list->count) if (!list)
return ERR_NULL_PTR; return ERR_NULL_PTR;
if (index < 0 || index >= list->count)
return ERR_INVALID_INDEX;
free(list->items[index]); free(list->items[index]);
for (int i = index; i < list->count - 1; i++) for (int i = index; i < list->count - 1; i++)
@@ -24,8 +26,10 @@ ErrorCode path_manager_remove_at(StringList *list, int index)
// 向上移动路径项 // 向上移动路径项
ErrorCode path_manager_move_up(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; return ERR_NULL_PTR;
if (index <= 0 || index >= list->count)
return ERR_INVALID_INDEX;
char *temp = list->items[index]; char *temp = list->items[index];
list->items[index] = list->items[index - 1]; list->items[index] = list->items[index - 1];
@@ -36,8 +40,10 @@ ErrorCode path_manager_move_up(StringList *list, int index)
// 向下移动路径项 // 向下移动路径项
ErrorCode path_manager_move_down(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; return ERR_NULL_PTR;
if (index < 0 || index >= list->count - 1)
return ERR_INVALID_INDEX;
char *temp = list->items[index]; char *temp = list->items[index];
list->items[index] = list->items[index + 1]; list->items[index] = list->items[index + 1];
+18 -33
View File
@@ -5,7 +5,16 @@
#include <wchar.h> #include <wchar.h>
#include <libintl.h> #include <libintl.h>
#include "core/app_context.h" #include "core/app_context.h"
#include "utils/ui_constants.h"
#include "core/lua_config.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/string_ext.h"
#include "utils/os_env.h" #include "utils/os_env.h"
#include "utils/logger.h" #include "utils/logger.h"
@@ -98,42 +107,18 @@ int main(int argc, char **argv)
{ {
IupMessage(_("Warning"), _(lua_config_get_string("status", "admin_warning"))); 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) if (lbl_status)
IupSetAttribute(lbl_status, "TITLE", _(lua_config_get_string("status", "readonly"))); IupSetAttribute(lbl_status, "TITLE", _(lua_config_get_string("status", "readonly")));
Ihandle *btn_new = IupGetDialogChild(dlg, "BTN_NEW"); // 禁用所有需要管理员权限的按钮
Ihandle *btn_edit = IupGetDialogChild(dlg, "BTN_EDIT"); for (int i = 0; i < ADMIN_DISABLE_COUNT; i++)
Ihandle *btn_browse = IupGetDialogChild(dlg, "BTN_BROWSE"); {
Ihandle *btn_del = IupGetDialogChild(dlg, "BTN_DEL"); Ihandle *btn = IupGetDialogChild(dlg, ADMIN_DISABLE_BUTTONS[i]);
Ihandle *btn_up = IupGetDialogChild(dlg, "BTN_UP"); if (btn)
Ihandle *btn_down = IupGetDialogChild(dlg, "BTN_DOWN"); IupSetAttribute(btn, "ACTIVE", "NO");
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");
} }
IupShowXY(dlg, IUP_CENTER, IUP_CENTER); IupShowXY(dlg, IUP_CENTER, IUP_CENTER);
+44 -66
View File
@@ -2,6 +2,7 @@
#include "controller/callbacks.h" #include "controller/callbacks.h"
#include "core/lua_config.h" #include "core/lua_config.h"
#include "utils/i18n.h" #include "utils/i18n.h"
#include "utils/ui_constants.h"
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
@@ -26,13 +27,13 @@ static Ihandle *create_path_list(const char *name)
Ihandle *create_main_window(void) 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); 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, "EXPAND", "HORIZONTAL");
IupSetAttribute(txt_search, "CUEBANNER", lua_config_get_string("label", "search_placeholder")); IupSetAttribute(txt_search, "CUEBANNER", lua_config_get_string("label", "search_placeholder"));
IupSetCallback(txt_search, "VALUECHANGED_CB", (Icallback)txt_search_cb); IupSetCallback(txt_search, "VALUECHANGED_CB", (Icallback)txt_search_cb);
@@ -42,42 +43,42 @@ Ihandle *create_main_window(void)
IupVbox(list_sys, NULL), IupVbox(list_sys, NULL),
IupVbox(list_user, NULL), IupVbox(list_user, NULL),
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, "TABTITLE0", _(lua_config_get_string("label", "tab_sys")));
IupSetAttribute(tabs_main, "TABTITLE1", _(lua_config_get_string("label", "tab_user"))); IupSetAttribute(tabs_main, "TABTITLE1", _(lua_config_get_string("label", "tab_user")));
IupSetAttribute(tabs_main, "TABTYPE", "TOP"); IupSetAttribute(tabs_main, "TABTYPE", "TOP");
// 创建操作按钮 // 创建操作按钮
Ihandle *btn_new = IupButton(_(lua_config_get_string("button", "new")), NULL); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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")); 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"); IupSetAttribute(lbl_status, "EXPAND", "HORIZONTAL");
// 创建底部按钮 // 创建底部按钮
Ihandle *btn_ok = IupButton(_(lua_config_get_string("button", "ok")), NULL); 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); 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); 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); IupSetCallback(btn_ok, "ACTION", (Icallback)btn_ok_cb);
@@ -176,60 +177,37 @@ void refresh_main_window_ui(Ihandle *main_dlg)
if (!main_dlg) if (!main_dlg)
return; return;
// 设置窗口标题
IupSetAttribute(main_dlg, "TITLE", _(lua_config_get_string("app", "name"))); IupSetAttribute(main_dlg, "TITLE", _(lua_config_get_string("app", "name")));
// 设置选项卡标题
IupSetAttribute(main_dlg, "TABTITLE0", _(lua_config_get_string("label", "tab_sys"))); IupSetAttribute(main_dlg, "TABTITLE0", _(lua_config_get_string("label", "tab_sys")));
IupSetAttribute(main_dlg, "TABTITLE1", _(lua_config_get_string("label", "tab_user"))); IupSetAttribute(main_dlg, "TABTITLE1", _(lua_config_get_string("label", "tab_user")));
Ihandle *btn = IupGetDialogChild(main_dlg, "BTN_NEW"); // 辅助函数:设置子控件标题
if (btn) #define SET_CHILD_TITLE(btn_name, text_key) \
IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "new"))); 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"); SET_CHILD_TITLE(CTRL_BTN_NEW, "new");
if (btn) SET_CHILD_TITLE(CTRL_BTN_EDIT, "edit");
IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "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"); #undef SET_CHILD_TITLE
if (btn)
IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "browse")));
btn = IupGetDialogChild(main_dlg, "BTN_DEL"); // 语言切换按钮标题单独处理(不是从配置读取)
if (btn) Ihandle *btn_lang = IupGetDialogChild(main_dlg, CTRL_BTN_LANG);
IupSetAttribute(btn, "TITLE", _(lua_config_get_string("button", "del"))); if (btn_lang)
IupSetAttribute(btn_lang, "TITLE", _("Language"));
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")));
} }
+71 -29
View File
@@ -5,6 +5,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#include <direct.h> #include <direct.h>
#include <shlobj.h>
// 检查管理员权限 // 检查管理员权限
int check_admin(void) 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 目录 // 获取 AppData 路径
if (_mkdir("records") == -1) 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); time_t t = time(NULL);
struct tm *tm_info = localtime(&t); struct tm *tm_info = localtime(&t);
char time_str[64]; wchar_t timestamp[64];
strftime(time_str, sizeof(time_str), "%Y%m%d_%H%M%S", tm_info); wcsftime(timestamp, sizeof(timestamp), L"%Y%m%d_%H%M%S", tm_info);
// 构造备份文件名 // 构造备份文件名
char filename[256]; wchar_t backup_file[MAX_PATH];
snprintf(filename, sizeof(filename), "records\\backup_%s.reg", time_str); swprintf(backup_file, MAX_PATH, L"%s\\path_backup_%s.txt", backup_dir, timestamp);
// 构造 reg export 命令 // 打开文件
char full_cmd[1024]; FILE *fp = _wfopen(backup_file, L"w, ccs=UTF-8");
snprintf(full_cmd, sizeof(full_cmd), "reg.exe export \"HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\" \"%s\" /y", filename); if (!fp)
return ERR_FAILED;
// 使用 CreateProcess 隐藏窗口执行 // 备份系统 PATH
STARTUPINFOA si; HKEY hKey;
PROCESS_INFORMATION pi; int success = 0;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE; // 隐藏窗口
memset(&pi, 0, sizeof(pi));
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)
{ {
// 等待进程结束 DWORD type, size;
WaitForSingleObject(pi.hProcess, INFINITE); if (RegQueryValueExW(hKey, L"Path", NULL, &type, NULL, &size) == ERROR_SUCCESS)
{
DWORD exit_code = 0; wchar_t *buffer = (wchar_t *)malloc(size + 2);
GetExitCodeProcess(pi.hProcess, &exit_code); if (buffer)
{
CloseHandle(pi.hProcess); memset(buffer, 0, size + 2);
CloseHandle(pi.hThread); 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;
} }