From 39d06e20e01213e6d8d5e5ab6cd3d283e7581c59 Mon Sep 17 00:00:00 2001 From: LHY0125 <3364451258@qq.com> Date: Mon, 16 Mar 2026 19:58:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E7=B3=BB=E7=BB=9F/?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=8F=98=E9=87=8F=E5=88=86=E7=A6=BB=E3=80=81?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E3=80=81=E6=8B=96=E6=8B=BD=E5=92=8C=E6=B8=85?= =?UTF-8?q?=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将单一列表拆分为系统和用户变量两个标签页 - 新增搜索框支持实时过滤路径 - 支持拖拽文件夹直接添加到列表 - 新增一键清理功能移除无效和重复路径 - 增加注册表备份机制和删除确认 - 优化界面布局和权限提示逻辑 --- bin/PathEditor.exe | Bin 219081 -> 229528 bytes bin/records/backup_20260316_193937.reg | Bin 0 -> 35938 bytes bin/records/backup_20260316_194700.reg | Bin 0 -> 35938 bytes bin/records/backup_20260316_195033.reg | Bin 0 -> 35938 bytes bin/records/backup_20260316_195233.reg | Bin 0 -> 35938 bytes bin/records/backup_20260316_195238.reg | Bin 0 -> 35938 bytes bin/records/backup_20260316_195622.reg | Bin 0 -> 35938 bytes include/callbacks.h | 30 ++- include/globals.h | 24 +- include/registry.h | 6 +- include/utils.h | 11 + src/callbacks.c | 296 +++++++++++++++++++++---- src/main.c | 84 +++++-- src/registry.c | 238 +++++++++----------- src/utils.c | 188 +++++++++++++++- 15 files changed, 668 insertions(+), 209 deletions(-) create mode 100644 bin/records/backup_20260316_193937.reg create mode 100644 bin/records/backup_20260316_194700.reg create mode 100644 bin/records/backup_20260316_195033.reg create mode 100644 bin/records/backup_20260316_195233.reg create mode 100644 bin/records/backup_20260316_195238.reg create mode 100644 bin/records/backup_20260316_195622.reg diff --git a/bin/PathEditor.exe b/bin/PathEditor.exe index 68d21bf968bc991fc2c6ea93c1b1bfde44a060c4..da6756031d54c84d4c368fbd22c948fdbf7de2d8 100644 GIT binary patch delta 41207 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 J%d?G%{|8QdRMh|g delta 31283 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 TF6v!g@v^i~>X=f&Bv1bzxWZp{ literal 0 HcmV?d00001 diff --git a/bin/records/backup_20260316_194700.reg b/bin/records/backup_20260316_194700.reg new file mode 100644 index 0000000000000000000000000000000000000000..02da0a979c5e8247d37cbbcf4305f4a35da170b4 GIT binary patch literal 35938 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 TF6v!g@v^i~>X=f&Bv1bzxWZp{ literal 0 HcmV?d00001 diff --git a/bin/records/backup_20260316_195033.reg b/bin/records/backup_20260316_195033.reg new file mode 100644 index 0000000000000000000000000000000000000000..02da0a979c5e8247d37cbbcf4305f4a35da170b4 GIT binary patch literal 35938 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 TF6v!g@v^i~>X=f&Bv1bzxWZp{ literal 0 HcmV?d00001 diff --git a/bin/records/backup_20260316_195233.reg b/bin/records/backup_20260316_195233.reg new file mode 100644 index 0000000000000000000000000000000000000000..02da0a979c5e8247d37cbbcf4305f4a35da170b4 GIT binary patch literal 35938 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 TF6v!g@v^i~>X=f&Bv1bzxWZp{ literal 0 HcmV?d00001 diff --git a/bin/records/backup_20260316_195238.reg b/bin/records/backup_20260316_195238.reg new file mode 100644 index 0000000000000000000000000000000000000000..02da0a979c5e8247d37cbbcf4305f4a35da170b4 GIT binary patch literal 35938 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 TF6v!g@v^i~>X=f&Bv1bzxWZp{ literal 0 HcmV?d00001 diff --git a/bin/records/backup_20260316_195622.reg b/bin/records/backup_20260316_195622.reg new file mode 100644 index 0000000000000000000000000000000000000000..02da0a979c5e8247d37cbbcf4305f4a35da170b4 GIT binary patch literal 35938 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 TF6v!g@v^i~>X=f&Bv1bzxWZp{ literal 0 HcmV?d00001 diff --git a/include/callbacks.h b/include/callbacks.h index ea7dcc3..f3c9009 100644 --- a/include/callbacks.h +++ b/include/callbacks.h @@ -4,17 +4,27 @@ #include // 按钮回调 -int btn_new_cb(Ihandle* self); -int btn_edit_cb(Ihandle* self); -int btn_browse_cb(Ihandle* self); -int btn_del_cb(Ihandle* self); -int btn_up_cb(Ihandle* self); -int btn_down_cb(Ihandle* self); -int btn_ok_cb(Ihandle* self); -int btn_cancel_cb(Ihandle* self); -int btn_help_cb(Ihandle* self); +int btn_new_cb(Ihandle *self); +int btn_edit_cb(Ihandle *self); +int btn_browse_cb(Ihandle *self); +int btn_del_cb(Ihandle *self); +int btn_up_cb(Ihandle *self); +int btn_down_cb(Ihandle *self); +int btn_clean_cb(Ihandle *self); +int btn_ok_cb(Ihandle *self); +int btn_cancel_cb(Ihandle *self); +int btn_help_cb(Ihandle *self); + +// 搜索回调 +int txt_search_cb(Ihandle *self); // 双击回调 -int list_dblclick_cb(Ihandle* self, int item, char* text); +int list_dblclick_cb(Ihandle *self, int item, char *text); + +// 拖拽回调 +int list_dropfiles_cb(Ihandle *self, const char *filename, int num, int x, int y); + +// 键盘按键回调 +int list_k_any_cb(Ihandle *self, int c); #endif // CALLBACKS_H \ No newline at end of file diff --git a/include/globals.h b/include/globals.h index ba69969..85e9949 100644 --- a/include/globals.h +++ b/include/globals.h @@ -4,12 +4,15 @@ #include // 注册表路径常量 -#define REG_PATH L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment" +#define REG_PATH_SYS L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment" +#define REG_PATH_USER L"Environment" #define REG_VALUE L"Path" // 全局控件句柄声明 extern Ihandle *dlg; // 主对话框句柄 -extern Ihandle *list_path; // 路径列表控件句柄 +extern Ihandle *tabs_main; // 标签页容器 +extern Ihandle *list_sys; // 系统变量列表 +extern Ihandle *list_user; // 用户变量列表 extern Ihandle *lbl_status; // 状态标签句柄 extern Ihandle *btn_new; // 新增按钮句柄 extern Ihandle *btn_edit; // 编辑按钮句柄 @@ -17,8 +20,25 @@ extern Ihandle *btn_browse; // 浏览按钮句柄 extern Ihandle *btn_del; // 删除按钮句柄 extern Ihandle *btn_up; // 上移按钮句柄 extern Ihandle *btn_down; // 下移按钮句柄 +extern Ihandle *btn_clean; // 一键清理按钮句柄 extern Ihandle *btn_ok; // 确认按钮句柄 extern Ihandle *btn_cancel; // 取消按钮句柄 extern Ihandle *btn_help; // 帮助按钮句柄 +extern Ihandle *txt_search; // 搜索框 + +// 简单字符串列表结构,用于搜索缓存 +typedef struct { + char **items; + int count; + int capacity; +} StringList; + +extern StringList raw_sys_paths; +extern StringList raw_user_paths; + +// 缓存操作函数声明 +void init_string_list(StringList *list); +void add_string_list(StringList *list, const char *str); +void clear_string_list(StringList *list); #endif // GLOBALS_H \ No newline at end of file diff --git a/include/registry.h b/include/registry.h index ac27727..c42d7bf 100644 --- a/include/registry.h +++ b/include/registry.h @@ -1,10 +1,10 @@ #ifndef REGISTRY_H #define REGISTRY_H -// 从注册表加载PATH到列表控件 -void load_path(); +// 从注册表加载所有PATH到列表控件 +void load_all_paths(); // 将列表控件中的PATH保存回注册表 -void save_path(); +void save_all_paths(); #endif // REGISTRY_H \ No newline at end of file diff --git a/include/utils.h b/include/utils.h index dd775a6..72be326 100644 --- a/include/utils.h +++ b/include/utils.h @@ -3,6 +3,7 @@ #include #include +#include // 宽字符转UTF-8 char* wide_to_utf8(const wchar_t* wstr); @@ -13,7 +14,17 @@ wchar_t* utf8_to_wide(const char* str); // 检查管理员权限 int check_admin(); +// 检查路径是否有效(存在且为目录) +int is_path_valid(const char *path); + // 刷新列表样式(斑马纹) void refresh_list_style(); +void refresh_single_list_style(Ihandle *list); + +// 备份注册表 +void backup_registry(); + +// 不区分大小写的字符串查找 +char *stristr(const char *haystack, const char *needle); #endif // UTILS_H \ No newline at end of file diff --git a/src/callbacks.c b/src/callbacks.c index 63605ef..97f7f0f 100644 --- a/src/callbacks.c +++ b/src/callbacks.c @@ -27,8 +27,8 @@ int show_custom_input_dialog(const char *title, const char *label_text, char *bu text, IupHbox( IupFill(), - IupButton("确定", "1"), // "1" will be returned by IupPopup - IupButton("取消", "0"), // "0" will be returned by IupPopup + IupButton("确定", "1"), // "1" 会被返回 + IupButton("取消", "0"), // "0" 会被返回 NULL), NULL)); @@ -132,6 +132,20 @@ int custom_input_dialog(const char *title, const char *label_text, char *buffer, return result; } +// 辅助函数:获取当前选中的列表 +Ihandle *get_current_list() +{ + // 获取当前选中的 Tab 索引 + // 注意:IupTabs 的 VALUE 属性在某些版本可能返回 handle,某些版本返回 pos + // 这里使用 IupGetInt(tabs_main, "VALUEPOS") 更稳妥 + int pos = IupGetInt(tabs_main, "VALUEPOS"); + if (pos == 0) + return list_sys; + if (pos == 1) + return list_user; + return list_sys; // 默认 +} + // 按钮回调:新建 int btn_new_cb(Ihandle *self) { @@ -140,13 +154,14 @@ int btn_new_cb(Ihandle *self) { if (strlen(buffer) > 0) { - int count = IupGetInt(list_path, "COUNT"); + Ihandle *current_list = get_current_list(); + int count = IupGetInt(current_list, "COUNT"); count++; - IupSetAttributeId(list_path, "", count, buffer); - IupSetInt(list_path, "COUNT", count); - IupSetInt(list_path, "VALUE", count); + IupSetAttributeId(current_list, "", count, buffer); + IupSetInt(current_list, "COUNT", count); + IupSetInt(current_list, "VALUE", count); - refresh_list_style(); + refresh_single_list_style(current_list); } } return IUP_DEFAULT; @@ -155,11 +170,12 @@ int btn_new_cb(Ihandle *self) // 按钮回调:编辑 int btn_edit_cb(Ihandle *self) { - int selected = IupGetInt(list_path, "VALUE"); + Ihandle *current_list = get_current_list(); + int selected = IupGetInt(current_list, "VALUE"); if (selected == 0) return IUP_DEFAULT; - char *current_val = IupGetAttributeId(list_path, "", selected); + char *current_val = IupGetAttributeId(current_list, "", selected); char buffer[4096]; // 假设单个路径不超过4096 if (current_val) { @@ -175,8 +191,8 @@ int btn_edit_cb(Ihandle *self) { if (strlen(buffer) > 0) { - IupSetAttributeId(list_path, "", selected, buffer); - refresh_list_style(); + IupSetAttributeId(current_list, "", selected, buffer); + refresh_single_list_style(current_list); } } return IUP_DEFAULT; @@ -185,11 +201,11 @@ int btn_edit_cb(Ihandle *self) // 双击回调 int list_dblclick_cb(Ihandle *self, int item, char *text) { - // 这里的 item 是点击的行号 + // 这里的 self 就是触发双击的列表控件 if (item > 0) { // 选中该行 - IupSetInt(list_path, "VALUE", item); + IupSetInt(self, "VALUE", item); // 调用编辑逻辑 btn_edit_cb(NULL); } @@ -210,42 +226,100 @@ int btn_browse_cb(Ihandle *self) char *value = IupGetAttribute(filedlg, "VALUE"); if (value) { - int count = IupGetInt(list_path, "COUNT"); + Ihandle *current_list = get_current_list(); + int count = IupGetInt(current_list, "COUNT"); count++; - IupSetAttributeId(list_path, "", count, value); - IupSetInt(list_path, "COUNT", count); - IupSetInt(list_path, "VALUE", count); + IupSetAttributeId(current_list, "", count, value); + IupSetInt(current_list, "COUNT", count); + IupSetInt(current_list, "VALUE", count); - refresh_list_style(); + refresh_single_list_style(current_list); } } IupDestroy(filedlg); return IUP_DEFAULT; } +// 辅助函数:从 raw_data 中删除指定字符串 +static void remove_from_raw_data(StringList *list, const char *str) +{ + if (!list || !str) + return; + for (int i = 0; i < list->count; i++) + { + if (strcmp(list->items[i], str) == 0) + { + free(list->items[i]); + // 移动后续元素 + for (int j = i; j < list->count - 1; j++) + { + list->items[j] = list->items[j + 1]; + } + list->count--; + break; // 假设没有重复,只删除第一个匹配 + } + } +} + // 按钮回调:删除 int btn_del_cb(Ihandle *self) { - int selected = IupGetInt(list_path, "VALUE"); + Ihandle *current_list = get_current_list(); + int selected = IupGetInt(current_list, "VALUE"); + if (selected == 0) + { + IupMessage("提示", "请先选择要删除的项"); return IUP_DEFAULT; + } - IupSetAttribute(list_path, "REMOVEITEM", "SELECTED"); + // 获取当前要删除的内容 + char *val = IupGetAttributeId(current_list, "", selected); + + // 确认删除 + // char msg[1024]; + // snprintf(msg, sizeof(msg), "确定要删除以下路径吗?\n\n%s", val ? val : "(空)"); + // if (IupAlarm("确认删除", msg, "是", "否", NULL) != 1) + // return IUP_DEFAULT; + + // 从 raw_data 缓存中同步删除 + int pos = IupGetInt(tabs_main, "VALUEPOS"); + StringList *raw_data = (pos == 0) ? &raw_sys_paths : &raw_user_paths; + + // 注意:必须先保存 val 的副本,因为 REMOVEITEM 可能会导致 val 指针失效(如果它是指向列表内部缓冲区的) + char *val_copy = val ? _strdup(val) : NULL; + + // 先从界面删除 + // IupSetAttribute(current_list, "REMOVEITEM", "SELECTED"); + // 改为按索引删除,防止失去焦点导致 SELECTED 失效 + IupSetInt(current_list, "REMOVEITEM", selected); + + // 再从缓存删除 + if (val_copy && raw_data) + { + remove_from_raw_data(raw_data, val_copy); + free(val_copy); + } + + // 重新刷新 + refresh_single_list_style(current_list); + + // 更新状态栏,告知用户删除了什么 + IupSetAttribute(lbl_status, "TITLE", "状态: 已删除选中项"); - // 重新刷新,因为删除了中间项,后面的奇偶性变了 - refresh_list_style(); return IUP_DEFAULT; } // 按钮回调:上移 int btn_up_cb(Ihandle *self) { - int selected = IupGetInt(list_path, "VALUE"); + Ihandle *current_list = get_current_list(); + int selected = IupGetInt(current_list, "VALUE"); if (selected <= 1) return IUP_DEFAULT; // 已经是第一个或未选中 - char *current = IupGetAttributeId(list_path, "", selected); - char *prev = IupGetAttributeId(list_path, "", selected - 1); + char *current = IupGetAttributeId(current_list, "", selected); + char *prev = IupGetAttributeId(current_list, "", selected - 1); // 交换内容 char buf_curr[4096], buf_prev[4096]; @@ -254,26 +328,27 @@ int btn_up_cb(Ihandle *self) strncpy(buf_prev, prev, 4096); buf_prev[4095] = '\0'; - IupSetAttributeId(list_path, "", selected, buf_prev); - IupSetAttributeId(list_path, "", selected - 1, buf_curr); + IupSetAttributeId(current_list, "", selected, buf_prev); + IupSetAttributeId(current_list, "", selected - 1, buf_curr); - IupSetInt(list_path, "VALUE", selected - 1); + IupSetInt(current_list, "VALUE", selected - 1); // 刷新样式(虽然颜色不需要变,但为了保险) - refresh_list_style(); + refresh_single_list_style(current_list); return IUP_DEFAULT; } // 按钮回调:下移 int btn_down_cb(Ihandle *self) { - int selected = IupGetInt(list_path, "VALUE"); - int count = IupGetInt(list_path, "COUNT"); + Ihandle *current_list = get_current_list(); + int selected = IupGetInt(current_list, "VALUE"); + int count = IupGetInt(current_list, "COUNT"); if (selected == 0 || selected >= count) return IUP_DEFAULT; - char *current = IupGetAttributeId(list_path, "", selected); - char *next = IupGetAttributeId(list_path, "", selected + 1); + char *current = IupGetAttributeId(current_list, "", selected); + char *next = IupGetAttributeId(current_list, "", selected + 1); char buf_curr[4096], buf_next[4096]; strncpy(buf_curr, current, 4096); @@ -281,19 +356,164 @@ int btn_down_cb(Ihandle *self) strncpy(buf_next, next, 4096); buf_next[4095] = '\0'; - IupSetAttributeId(list_path, "", selected, buf_next); - IupSetAttributeId(list_path, "", selected + 1, buf_curr); + IupSetAttributeId(current_list, "", selected, buf_next); + IupSetAttributeId(current_list, "", selected + 1, buf_curr); - IupSetInt(list_path, "VALUE", selected + 1); + IupSetInt(current_list, "VALUE", selected + 1); - refresh_list_style(); + refresh_single_list_style(current_list); + return IUP_DEFAULT; +} + +// 按钮回调:一键清理 +int btn_clean_cb(Ihandle *self) +{ + Ihandle *current_list = get_current_list(); + int count = IupGetInt(current_list, "COUNT"); + if (count == 0) + return IUP_DEFAULT; + + // 弹出确认对话框 + if (IupAlarm("确认清理", "此操作将移除当前列表中所有【无效路径】和【重复路径】。\n确定要继续吗?", "确定", "取消", NULL) != 1) + { + return IUP_DEFAULT; + } + + // 从后往前遍历删除,避免索引错位 + for (int i = count; i >= 1; i--) + { + char *item = IupGetAttributeId(current_list, "", i); + if (!item) + continue; + + int should_remove = 0; + + // 1. 检查有效性 + if (!is_path_valid(item)) + { + should_remove = 1; + } + else + { + // 2. 检查重复 (检查当前项之前是否出现过) + // 注意:这里需要再次遍历,性能稍低但最稳妥 + for (int j = 1; j < i; j++) + { + char *prev_item = IupGetAttributeId(current_list, "", j); + if (prev_item && _stricmp(item, prev_item) == 0) + { + should_remove = 1; + break; + } + } + } + + if (should_remove) + { + IupSetAttributeId(current_list, "REMOVEITEM", i, NULL); + } + } + + refresh_single_list_style(current_list); + IupMessage("提示", "清理完成!"); + return IUP_DEFAULT; +} + +// 搜索回调 +int txt_search_cb(Ihandle *self) +{ + char *filter = IupGetAttribute(self, "VALUE"); + if (!filter) + return IUP_DEFAULT; + + // 获取当前选中的 Tab 索引 + int pos = IupGetInt(tabs_main, "VALUEPOS"); + Ihandle *current_list = (pos == 0) ? list_sys : list_user; + StringList *raw_data = (pos == 0) ? &raw_sys_paths : &raw_user_paths; + + // 清空列表 + IupSetAttribute(current_list, "REMOVEITEM", "ALL"); + + // 重新填充 + int count = 0; + for (int i = 0; i < raw_data->count; i++) + { + // 如果 filter 为空,或包含 filter (不区分大小写) + if (strlen(filter) == 0 || stristr(raw_data->items[i], filter) != NULL) + { + count++; + IupSetAttributeId(current_list, "", count, raw_data->items[i]); + } + } + + IupSetInt(current_list, "COUNT", count); + refresh_single_list_style(current_list); + + return IUP_DEFAULT; +} + +// 拖拽回调 +int list_dropfiles_cb(Ihandle *self, const char *filename, int num, int x, int y) +{ + // 获取当前列表和原始数据 + // 注意:拖拽的目标列表可能是 list_sys 或 list_user,由 self 参数决定 + // 但为了确保数据一致性,我们还是重新获取一下 + Ihandle *current_list = self; + StringList *raw_data = NULL; + if (self == list_sys) + raw_data = &raw_sys_paths; + else if (self == list_user) + raw_data = &raw_user_paths; + else + return IUP_DEFAULT; // 异常情况 + + // 检查拖入的是否为目录 + DWORD attr = GetFileAttributesA(filename); + if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY)) + { + // 如果正在搜索,先清空搜索框 + IupSetAttribute(txt_search, "VALUE", ""); + + // 添加到列表末尾 + int count = IupGetInt(current_list, "COUNT"); + count++; + IupSetAttributeId(current_list, "", count, filename); + IupSetInt(current_list, "COUNT", count); + IupSetInt(current_list, "VALUE", count); // 选中新添加的项 + + // 同时添加到原始数据缓存,确保搜索时能搜到 + if (raw_data) + { + add_string_list(raw_data, filename); + } + + refresh_single_list_style(current_list); + } + else + { + // 如果拖入的不是文件夹,可以在状态栏提示 + IupSetAttribute(lbl_status, "TITLE", "提示: 只能拖拽文件夹添加到 PATH"); + } + + return IUP_DEFAULT; +} + +// 键盘按键回调 +int list_k_any_cb(Ihandle *self, int c) +{ + // 处理 Delete 键 + if (c == K_DEL) + { + btn_del_cb(NULL); + return IUP_IGNORE; // 阻止默认处理 + } return IUP_DEFAULT; } // 按钮回调:确定 int btn_ok_cb(Ihandle *self) { - save_path(); + save_all_paths(); return IUP_DEFAULT; } diff --git a/src/main.c b/src/main.c index 77ef73c..fa1afbf 100644 --- a/src/main.c +++ b/src/main.c @@ -8,10 +8,32 @@ #include "registry.h" #include "callbacks.h" +// 全局变量定义 +StringList raw_sys_paths = {0}; +StringList raw_user_paths = {0}; + // 全局控件定义 -Ihandle *dlg, *list_path, *lbl_status; -Ihandle *btn_new, *btn_edit, *btn_browse, *btn_del, *btn_up, *btn_down; -Ihandle *btn_ok, *btn_cancel, *btn_help; +Ihandle *dlg, *tabs_main, *list_sys, *list_user, *lbl_status; // 主窗口、标签页、系统路径列表、用户路径列表、状态标签 +Ihandle *btn_new, *btn_edit, *btn_browse, *btn_del, *btn_up, *btn_down; // 右侧按钮 +Ihandle *btn_ok, *btn_cancel, *btn_help; // 确认取消帮助按钮 +Ihandle *btn_clean; // 一键清理按钮 +Ihandle *txt_search; // 搜索框 + +// 辅助函数:创建列表控件 +Ihandle *create_path_list() +{ + Ihandle *list = IupFlatList(); + IupSetAttribute(list, "EXPAND", "YES"); + IupSetAttribute(list, "ITEMPADDING", "5x5"); + IupSetAttribute(list, "BACKCOLOR", "255 255 255"); + IupSetAttribute(list, "BORDER", "YES"); + IupSetAttribute(list, "CANFOCUS", "YES"); + IupSetAttribute(list, "HLINE", "NO"); + IupSetCallback(list, "DBLCLICK_CB", (Icallback)list_dblclick_cb); + IupSetCallback(list, "DROPFILES_CB", (Icallback)list_dropfiles_cb); + IupSetCallback(list, "K_ANY", (Icallback)list_k_any_cb); + return list; +} // 主函数 int main(int argc, char **argv) @@ -22,15 +44,24 @@ int main(int argc, char **argv) IupOpen(&argc, &argv); IupSetGlobal("UTF8MODE", "YES"); - // 创建列表控件 - list_path = IupFlatList(); - IupSetAttribute(list_path, "EXPAND", "YES"); - IupSetAttribute(list_path, "ITEMPADDING", "5x5"); - IupSetAttribute(list_path, "BACKCOLOR", "255 255 255"); - IupSetAttribute(list_path, "BORDER", "YES"); - IupSetAttribute(list_path, "CANFOCUS", "YES"); - IupSetAttribute(list_path, "HLINE", "NO"); // 禁用横线,使用斑马纹 - // IupFlatList 不支持 VISIBLELINES,高度由 EXPAND 和布局决定 + // 创建两个列表控件 + list_sys = create_path_list(); + list_user = create_path_list(); + + // 创建搜索框 + txt_search = IupText(NULL); + IupSetAttribute(txt_search, "EXPAND", "HORIZONTAL"); + IupSetAttribute(txt_search, "CUEBANNER", "输入关键词搜索..."); + IupSetCallback(txt_search, "VALUECHANGED_CB", (Icallback)txt_search_cb); + + // 创建 Tabs + tabs_main = IupTabs( + IupVbox(list_sys, NULL), + IupVbox(list_user, NULL), + NULL); + IupSetAttribute(tabs_main, "TABTITLE0", "系统变量 (System)"); + IupSetAttribute(tabs_main, "TABTITLE1", "用户变量 (User)"); + IupSetAttribute(tabs_main, "TABTYPE", "TOP"); // 创建右侧按钮 btn_new = IupButton("新建(N)", NULL); @@ -39,6 +70,7 @@ int main(int argc, char **argv) btn_del = IupButton("删除(D)", NULL); btn_up = IupButton("上移(U)", NULL); btn_down = IupButton("下移(O)", NULL); + btn_clean = IupButton("一键清理", NULL); // 设置按钮回调 IupSetCallback(btn_new, "ACTION", (Icallback)btn_new_cb); @@ -47,9 +79,7 @@ int main(int argc, char **argv) IupSetCallback(btn_del, "ACTION", (Icallback)btn_del_cb); IupSetCallback(btn_up, "ACTION", (Icallback)btn_up_cb); IupSetCallback(btn_down, "ACTION", (Icallback)btn_down_cb); - - // 设置双击回调 - IupSetCallback(list_path, "DBLCLICK_CB", (Icallback)list_dblclick_cb); + IupSetCallback(btn_clean, "ACTION", (Icallback)btn_clean_cb); // 设置按钮大小 (宽度和高度都增加约1/4) IupSetAttribute(btn_new, "RASTERSIZE", "100x32"); @@ -58,17 +88,20 @@ int main(int argc, char **argv) IupSetAttribute(btn_del, "RASTERSIZE", "100x32"); IupSetAttribute(btn_up, "RASTERSIZE", "100x32"); IupSetAttribute(btn_down, "RASTERSIZE", "100x32"); + IupSetAttribute(btn_clean, "RASTERSIZE", "100x32"); Ihandle *vbox_btns = IupVbox( btn_new, btn_edit, btn_browse, btn_del, IupFill(), // 间隔 + btn_clean, // 放在上移下移之前,或者最下面,这里放在中间偏下 + IupFill(), btn_up, btn_down, NULL); IupSetAttribute(vbox_btns, "GAP", "5"); IupSetAttribute(vbox_btns, "MARGIN", "0x0"); - // 上部布局:列表 + 按钮 - Ihandle *hbox_main = IupHbox(list_path, vbox_btns, NULL); + // 上部布局:Tabs + 按钮 + Ihandle *hbox_main = IupHbox(tabs_main, vbox_btns, NULL); IupSetAttribute(hbox_main, "GAP", "10"); IupSetAttribute(hbox_main, "MARGIN", "10x10"); @@ -96,7 +129,8 @@ int main(int argc, char **argv) // 总体布局 Ihandle *vbox_all = IupVbox( - IupLabel("系统变量 Path:"), + IupLabel("环境变量编辑器:"), + txt_search, hbox_main, hbox_bottom, NULL); @@ -106,7 +140,7 @@ int main(int argc, char **argv) // 创建对话框 dlg = IupDialog(vbox_all); IupSetAttribute(dlg, "TITLE", "编辑环境变量 (IUP版)"); - IupSetAttribute(dlg, "SIZE", "450x350"); + IupSetAttribute(dlg, "SIZE", "500x400"); // 稍微调大一点 IupSetAttribute(dlg, "MINBOX", "NO"); IupSetAttribute(dlg, "MAXBOX", "NO"); @@ -116,13 +150,23 @@ int main(int argc, char **argv) IupMessage("警告", "程序未以管理员身份运行,您只能查看,无法保存更改!"); IupSetAttribute(dlg, "TITLE", "编辑环境变量 (只读模式)"); IupSetAttribute(lbl_status, "TITLE", "状态: 只读模式 (权限不足)"); + + // 禁用修改类按钮 + IupSetAttribute(btn_new, "ACTIVE", "NO"); + IupSetAttribute(btn_edit, "ACTIVE", "NO"); + IupSetAttribute(btn_browse, "ACTIVE", "NO"); + IupSetAttribute(btn_del, "ACTIVE", "NO"); + IupSetAttribute(btn_up, "ACTIVE", "NO"); + IupSetAttribute(btn_down, "ACTIVE", "NO"); + IupSetAttribute(btn_clean, "ACTIVE", "NO"); + IupSetAttribute(btn_ok, "ACTIVE", "NO"); } IupShowXY(dlg, IUP_CENTER, IUP_CENTER); // IUP List APPEND 属性需要在控件 Map 之后才能生效 // IupShowXY 会触发 Map - load_path(); + load_all_paths(); IupMainLoop(); IupClose(); diff --git a/src/registry.c b/src/registry.c index 1b9f6bb..51cd288 100644 --- a/src/registry.c +++ b/src/registry.c @@ -6,17 +6,23 @@ #include #include -// 从注册表加载PATH -void load_path() +// 内部辅助函数:加载单个列表 +static void load_single_path(HKEY hKeyRoot, const wchar_t *regPath, Ihandle *list, StringList *cache) { + // 清空旧缓存 + clear_string_list(cache); + HKEY hKey; - LONG res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, REG_PATH, 0, KEY_READ, &hKey); + LONG res = RegOpenKeyExW(hKeyRoot, regPath, 0, KEY_READ, &hKey); if (res != ERROR_SUCCESS) { - char msg[512]; - snprintf(msg, sizeof(msg), "无法打开注册表键 (HKLM)。\n路径: %ls\n错误码: %ld\n\n请尝试右键点击程序 -> '以管理员身份运行'。", REG_PATH, res); - IupMessage("错误", msg); - IupSetAttribute(lbl_status, "TITLE", "状态: 注册表读取失败"); + // 只有 HKLM 失败才提示需要管理员,HKCU 失败可能是其他原因 + if (hKeyRoot == HKEY_LOCAL_MACHINE) + { + char msg[512]; + snprintf(msg, sizeof(msg), "无法打开注册表键 (HKLM)。\n路径: %ls\n错误码: %ld\n\n请尝试右键点击程序 -> '以管理员身份运行'。", regPath, res); + IupMessage("错误", msg); + } return; } @@ -24,172 +30,148 @@ void load_path() res = RegQueryValueExW(hKey, REG_VALUE, NULL, &type, NULL, &size); if (res == ERROR_SUCCESS) { - // 安全分配内存:size 是字节数,多分配 2 个字节给 null 终止符 wchar_t *buffer = (wchar_t *)malloc(size + 2); - if (!buffer) + if (buffer) { - IupMessage("错误", "内存分配失败!"); - RegCloseKey(hKey); - return; - } - - // 初始化内存 - memset(buffer, 0, size + 2); - - if (RegQueryValueExW(hKey, REG_VALUE, NULL, &type, (LPBYTE)buffer, &size) == ERROR_SUCCESS) - { - // 重新实现分割逻辑,避免 wcstok 的兼容性问题 - wchar_t *current = buffer; - wchar_t *next_semicolon = NULL; - int count = 0; - - // 清空列表 - IupSetAttribute(list_path, "REMOVEITEM", "ALL"); - - // 检查内容是否为空 - if (wcslen(buffer) == 0) + memset(buffer, 0, size + 2); + if (RegQueryValueExW(hKey, REG_VALUE, NULL, &type, (LPBYTE)buffer, &size) == ERROR_SUCCESS) { - IupMessage("提示", "读取到的 PATH 变量为空!"); + wchar_t *current = buffer; + wchar_t *next_semicolon = NULL; + int count = 0; + + IupSetAttribute(list, "REMOVEITEM", "ALL"); + + while (*current) + { + next_semicolon = wcschr(current, L';'); + if (next_semicolon) + *next_semicolon = L'\0'; + + if (wcslen(current) > 0) + { + char *utf8_str = wide_to_utf8(current); + + // 添加到列表 + count++; + IupSetAttributeId(list, "", count, utf8_str); + + // 添加到缓存 + add_string_list(cache, utf8_str); + + free(utf8_str); + } + + if (next_semicolon) + current = next_semicolon + 1; + else + break; + } + + IupSetInt(list, "COUNT", count); + IupSetInt(list, "VALUE", 1); } - - while (*current) - { - // 查找下一个分号 - next_semicolon = wcschr(current, L';'); - if (next_semicolon) - { - *next_semicolon = L'\0'; // 临时截断 - } - - // 跳过空项 - if (wcslen(current) > 0) - { - char *utf8_str = wide_to_utf8(current); - - count++; - IupSetAttributeId(list_path, "", count, utf8_str); - - free(utf8_str); - } - - if (next_semicolon) - { - current = next_semicolon + 1; - } - else - { - break; - } - } - - IupSetInt(list_path, "COUNT", count); // 显式设置列表项数量 - IupSetInt(list_path, "VALUE", 1); // 选中第一项 - - // 刷新斑马纹样式 - refresh_list_style(); - - char status_msg[100]; - sprintf(status_msg, "状态: 已加载 %d 个条目", count); - IupSetAttribute(lbl_status, "TITLE", status_msg); + free(buffer); } - else - { - IupMessage("错误", "读取 PATH 值内容失败!"); - IupSetAttribute(lbl_status, "TITLE", "状态: 读取值内容失败"); - } - free(buffer); - } - else - { - char msg[256]; - sprintf(msg, "查询 PATH 值大小失败。错误码: %ld", res); - IupMessage("错误", msg); - IupSetAttribute(lbl_status, "TITLE", "状态: 查询值失败"); } RegCloseKey(hKey); } -// 保存PATH到注册表 -void save_path() +// 加载所有PATH +void load_all_paths() { - if (!check_admin()) - { - IupMessage("错误", "需要管理员权限才能保存更改!\n请重新以管理员身份运行程序。"); - return; - } + load_single_path(HKEY_LOCAL_MACHINE, REG_PATH_SYS, list_sys, &raw_sys_paths); + load_single_path(HKEY_CURRENT_USER, REG_PATH_USER, list_user, &raw_user_paths); - int count = IupGetInt(list_path, "COUNT"); - if (count == 0) - { - // 警告:清空PATH是很危险的 - if (IupAlarm("警告", "PATH 为空!这可能导致系统命令无法使用。\n确定要保存吗?", "确定", "取消", NULL) != 1) - { - return; - } - } + refresh_list_style(); + IupSetAttribute(lbl_status, "TITLE", "状态: 已加载系统和用户变量"); +} - // 计算所需缓冲区大小 +// 内部辅助函数:保存单个列表 +static int save_single_path(HKEY hKeyRoot, const wchar_t *regPath, Ihandle *list) +{ + int count = IupGetInt(list, "COUNT"); + + // 计算大小 size_t total_len = 0; for (int i = 1; i <= count; i++) { - char *item = IupGetAttributeId(list_path, "", i); + char *item = IupGetAttributeId(list, "", i); if (item) { wchar_t *witem = utf8_to_wide(item); - total_len += wcslen(witem) + 1; // +1 for ';' + total_len += wcslen(witem) + 1; free(witem); } } - total_len += 1; // null terminator + total_len += 1; wchar_t *buffer = (wchar_t *)malloc(total_len * sizeof(wchar_t)); if (!buffer) - { - IupMessage("错误", "内存分配失败 (保存时)!"); - return; - } - buffer[0] = L'\0'; + return 0; + buffer[0] = L'\0'; for (int i = 1; i <= count; i++) { - char *item = IupGetAttributeId(list_path, "", i); + char *item = IupGetAttributeId(list, "", i); if (item) { wchar_t *witem = utf8_to_wide(item); wcscat(buffer, witem); if (i < count) - { wcscat(buffer, L";"); - } free(witem); } } - // 写入注册表 HKEY hKey; - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, REG_PATH, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS) + int success = 0; + if (RegOpenKeyExW(hKeyRoot, regPath, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS) { - // 使用 REG_EXPAND_SZ 类型,因为 PATH 可能包含 %SystemRoot% DWORD size = (wcslen(buffer) + 1) * sizeof(wchar_t); if (RegSetValueExW(hKey, REG_VALUE, 0, REG_EXPAND_SZ, (LPBYTE)buffer, size) == ERROR_SUCCESS) { - // 发送系统广播通知环境变量已更改 - SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 5000, NULL); - IupMessage("成功", "PATH 环境变量已更新!"); - IupSetAttribute(lbl_status, "TITLE", "状态: 保存成功"); - } - else - { - IupMessage("错误", "写入注册表失败!"); - IupSetAttribute(lbl_status, "TITLE", "状态: 保存失败"); + success = 1; } RegCloseKey(hKey); } - else - { - IupMessage("错误", "无法打开注册表进行写入。请检查权限!"); - IupSetAttribute(lbl_status, "TITLE", "状态: 打开注册表失败"); - } free(buffer); + return success; +} + +// 保存所有PATH +void save_all_paths() +{ + if (!check_admin()) + { + IupMessage("错误", "需要管理员权限才能保存更改!"); + return; + } + + // 备份 + backup_registry(); + + int sys_ok = save_single_path(HKEY_LOCAL_MACHINE, REG_PATH_SYS, list_sys); + int user_ok = save_single_path(HKEY_CURRENT_USER, REG_PATH_USER, list_user); + + if (sys_ok && user_ok) + { + SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 5000, NULL); + IupMessage("成功", "系统和用户 PATH 环境变量均已更新!"); + IupSetAttribute(lbl_status, "TITLE", "状态: 全部保存成功"); + } + else if (sys_ok) + { + IupMessage("提示", "系统变量保存成功,但用户变量保存失败。"); + } + else if (user_ok) + { + IupMessage("提示", "用户变量保存成功,但系统变量保存失败。"); + } + else + { + IupMessage("错误", "保存失败!"); + IupSetAttribute(lbl_status, "TITLE", "状态: 保存失败"); + } } \ No newline at end of file diff --git a/src/utils.c b/src/utils.c index 8514d69..cd8dc28 100644 --- a/src/utils.c +++ b/src/utils.c @@ -3,6 +3,9 @@ #include #include #include +#include +#include +#include // 宽字符转UTF-8 (用于IUP显示) char *wide_to_utf8(const wchar_t *wstr) @@ -39,23 +42,192 @@ int check_admin() return 0; } -// 刷新列表样式(斑马纹) -void refresh_list_style() +// 检查路径是否存在 +static int path_exists(const char *path) { - if (!list_path) + // 如果包含 %,说明是变量,无法直接检查存在性,默认视为有效 + if (strchr(path, '%')) + return 1; + + wchar_t *wpath = utf8_to_wide(path); + if (!wpath) + return 0; + + DWORD attr = GetFileAttributesW(wpath); + free(wpath); + + if (attr == INVALID_FILE_ATTRIBUTES) + return 0; + return (attr & FILE_ATTRIBUTE_DIRECTORY); // 必须是目录 +} + +// 检查路径是否存在(公开给外部使用) +int is_path_valid(const char *path) +{ + return path_exists(path); +} + +// 刷新列表样式(斑马纹 + 有效性检查) +void refresh_single_list_style(Ihandle *list) +{ + if (!list) return; - int count = IupGetInt(list_path, "COUNT"); + int count = IupGetInt(list, "COUNT"); + + // 用于查重的简单数组(实际项目可以用哈希表) + // 为了简单,我们只用双重循环检查重复,性能在几百个条目下没问题 + for (int i = 1; i <= count; i++) { - // 奇数行:白色 - // 偶数行:极浅灰色 (245 245 245) + char *item = IupGetAttributeId(list, "", i); + if (!item) + continue; + + // 默认颜色:黑字 + char fg_color[32] = "0 0 0"; + + // 1. 检查有效性 + if (!path_exists(item)) + { + // 无效路径:红色 + sprintf(fg_color, "255 0 0"); + } + + // 2. 检查重复 (只检查当前项之前的项,如果之前出现过,当前项标橙) + for (int j = 1; j < i; j++) + { + char *prev_item = IupGetAttributeId(list, "", j); + if (prev_item && _stricmp(item, prev_item) == 0) // Windows 路径不区分大小写 + { + // 重复路径:橙色 + sprintf(fg_color, "255 128 0"); + break; + } + } + + IupSetAttributeId(list, "ITEMFGCOLOR", i, fg_color); + + // 斑马纹背景 if (i % 2 == 0) { - IupSetAttributeId(list_path, "ITEMBGCOLOR", i, "245 245 245"); + IupSetAttributeId(list, "ITEMBGCOLOR", i, "245 245 245"); } else { - IupSetAttributeId(list_path, "ITEMBGCOLOR", i, "255 255 255"); + IupSetAttributeId(list, "ITEMBGCOLOR", i, "255 255 255"); } } +} + +// 刷新所有列表样式 +void refresh_list_style() +{ + refresh_single_list_style(list_sys); + refresh_single_list_style(list_user); +} + +// 备份注册表 +void backup_registry() +{ + // 创建 records 目录 + if (_mkdir("records") == -1) + { + // 目录可能已存在,忽略错误 + } + + // 获取当前时间 + 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); + + // 构造备份文件名 + char filename[256]; + snprintf(filename, sizeof(filename), "records\\backup_%s.reg", time_str); + + // 构造 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); + + // 使用 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)); + + if (CreateProcessA(NULL, full_cmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) + { + // 等待进程结束 + WaitForSingleObject(pi.hProcess, INFINITE); + + DWORD exit_code = 0; + GetExitCodeProcess(pi.hProcess, &exit_code); + + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } +} + +// 初始化字符串列表 +void init_string_list(StringList *list) +{ + list->items = NULL; + list->count = 0; + list->capacity = 0; +} + +// 不区分大小写的字符串查找 (简单实现) +char *stristr(const char *haystack, const char *needle) +{ + if (!haystack || !needle) + return NULL; + if (*needle == '\0') + return (char *)haystack; + + const char *h = haystack; + const char *n = needle; + const char *h_start = haystack; + + while (*h) + { + h_start = h; + n = needle; + while (*h && *n && (tolower((unsigned char)*h) == tolower((unsigned char)*n))) + { + h++; + n++; + } + if (*n == '\0') + return (char *)h_start; + h = h_start + 1; + } + return NULL; +} + +// 添加字符串到列表 +void add_string_list(StringList *list, const char *str) +{ + if (list->count >= list->capacity) + { + list->capacity = (list->capacity == 0) ? 16 : list->capacity * 2; + list->items = (char **)realloc(list->items, list->capacity * sizeof(char *)); + } + list->items[list->count] = _strdup(str); // 复制字符串 + list->count++; +} + +// 清空字符串列表 +void clear_string_list(StringList *list) +{ + for (int i = 0; i < list->count; i++) + { + free(list->items[i]); + } + free(list->items); + list->items = NULL; + list->count = 0; + list->capacity = 0; } \ No newline at end of file