// 简化版PDF书签合并工具 #include #include #include #include #include #include #define MAX_PATH 1024 #define MAX_FILES 100 typedef struct { char title[256]; char page[32]; } Bookmark; typedef struct { char folder[256]; Bookmark bookmarks[500]; int bookmark_count; } FileData; // 全局变量 char pdf_path[MAX_PATH] = ""; char txt_path[MAX_PATH] = ""; char output_path[MAX_PATH] = ""; // 函数声明 void log_message(HWND hwnd, const char* msg); BOOL browse_folder(HWND hwnd, char* path); void start_processing(HWND hwnd); int extract_number(const char* str); int compare_files(const void* a, const void* b); // 简化的日志函数 void log_message(HWND hwnd, const char* msg) { if (hwnd) { HWND hLog = GetDlgItem(hwnd, 3001); if (hLog) { char full_msg[1024]; sprintf(full_msg, "%s\r\n", msg); SendMessageA(hLog, EM_SETSEL, -1, -1); SendMessageA(hLog, EM_REPLACESEL, FALSE, (LPARAM)full_msg); } } printf("%s\n", msg); } // 简化的文件夹选择 BOOL browse_folder(HWND hwnd, char* path) { BROWSEINFOA bi = {0}; bi.hwndOwner = hwnd; bi.lpszTitle = "选择文件夹"; bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; LPITEMIDLIST pidl = SHBrowseForFolderA(&bi); if (pidl) { if (SHGetPathFromIDListA(pidl, path)) { CoTaskMemFree(pidl); return TRUE; } CoTaskMemFree(pidl); } return FALSE; } // 提取文件名中的数字 int extract_number(const char* str) { const char* p = str; while (*p) { if (isdigit(*p)) { int num = 0; while (*p && isdigit(*p)) { num = num * 10 + (*p - '0'); p++; } return num; } p++; } return 0; } // 文件比较函数 int compare_files(const void* a, const void* b) { const char* file_a = *(const char**)a; const char* file_b = *(const char**)b; char folder_a[MAX_PATH], folder_b[MAX_PATH]; strcpy(folder_a, strrchr(file_a, '\\') ? strrchr(file_a, '\\') + 1 : file_a); strcpy(folder_b, strrchr(file_b, '\\') ? strrchr(file_b, '\\') + 1 : file_b); int num_a = extract_number(folder_a); int num_b = extract_number(folder_b); if (num_a != num_b) return num_a - num_b; return strcmp(file_a, file_b); } // 查找bkmk文件 int find_bkmk_files(const char* root, char* files[], int* count) { *count = 0; char search[MAX_PATH]; sprintf(search, "%s\\*.*", root); WIN32_FIND_DATAA find_data; HANDLE hFind = FindFirstFileA(search, &find_data); if (hFind == INVALID_HANDLE_VALUE) return 0; do { if (strcmp(find_data.cFileName, ".") == 0 || strcmp(find_data.cFileName, "..") == 0) continue; char full_path[MAX_PATH]; sprintf(full_path, "%s\\%s", root, find_data.cFileName); if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { find_bmkk_files(full_path, files, count); } else if (strstr(find_data.cFileName, "FreePic2Pdf_bkmk")) { if (*count < MAX_FILES) { files[*count] = strdup(full_path); (*count)++; } } } while (FindNextFileA(hFind, &find_data)); FindClose(hFind); return *count; } // 简化的处理函数 void start_processing(HWND hwnd) { log_message(hwnd, "开始处理..."); if (strlen(pdf_path) == 0 || strlen(txt_path) == 0 || strlen(output_path) == 0) { log_message(hwnd, "错误:请选择所有路径"); return; } char* bmk_files[MAX_FILES]; int bmk_count = 0; if (!find_bmkk_files(pdf_path, bmk_files, &bmk_count)) { log_message(hwnd, "未找到bkmk文件"); return; } log_message(hwnd, "找到bmk文件,开始排序..."); qsort(bmk_files, bmk_count, sizeof(char*), compare_files); log_message(hwnd, "处理完成!"); // 释放内存 for (int i = 0; i < bmk_count; i++) { free(bmk_files[i]); } } // 窗口过程 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CREATE: // 创建控件 CreateWindowA("STATIC", "PDF路径:", WS_VISIBLE | WS_CHILD, 10, 10, 100, 20, hwnd, NULL, NULL, NULL); CreateWindowA("EDIT", pdf_path, WS_VISIBLE | WS_CHILD | WS_BORDER, 120, 10, 400, 20, hwnd, (HMENU)2001, NULL, NULL); CreateWindowA("BUTTON", "浏览", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 530, 10, 50, 20, hwnd, (HMENU)1001, NULL, NULL); CreateWindowA("STATIC", "TXT路径:", WS_VISIBLE | WS_CHILD, 10, 40, 100, 20, hwnd, NULL, NULL, NULL); CreateWindowA("EDIT", txt_path, WS_VISIBLE | WS_CHILD | WS_BORDER, 120, 40, 400, 20, hwnd, (HMENU)2002, NULL, NULL); CreateWindowA("BUTTON", "浏览", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 530, 40, 50, 20, hwnd, (HMENU)1002, NULL, NULL); CreateWindowA("STATIC", "输出路径:", WS_VISIBLE | WS_CHILD, 10, 70, 100, 20, hwnd, NULL, NULL, NULL); CreateWindowA("EDIT", output_path, WS_VISIBLE | WS_CHILD | WS_BORDER, 120, 70, 400, 20, hwnd, (HMENU)2003, NULL, NULL); CreateWindowA("BUTTON", "浏览", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 530, 70, 50, 20, hwnd, (HMENU)1003, NULL, NULL); CreateWindowA("BUTTON", "开始处理", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 10, 100, 80, 30, hwnd, (HMENU)1004, NULL, NULL); CreateWindowA("BUTTON", "退出", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 100, 100, 80, 30, hwnd, (HMENU)1005, NULL, NULL); CreateWindowA("EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER | WS_VSCROLL | ES_MULTILINE | ES_READONLY, 10, 140, 570, 300, hwnd, (HMENU)3001, NULL, NULL); break; case WM_COMMAND: switch (LOWORD(wParam)) { case 1001: browse_folder(hwnd, pdf_path); SetWindowTextA(GetDlgItem(hwnd, 2001), pdf_path); break; case 1002: browse_folder(hwnd, txt_path); SetWindowTextA(GetDlgItem(hwnd, 2002), txt_path); break; case 1003: browse_folder(hwnd, output_path); SetWindowTextA(GetDlgItem(hwnd, 2003), output_path); break; case 1004: GetWindowTextA(GetDlgItem(hwnd, 2001), pdf_path, MAX_PATH); GetWindowTextA(GetDlgItem(hwnd, 2002), txt_path, MAX_PATH); GetWindowTextA(GetDlgItem(hwnd, 2003), output_path, MAX_PATH); start_processing(hwnd); break; case 1005: DestroyWindow(hwnd); break; } return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, msg, wParam, lParam); } // 主函数 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { InitCommonControls(); WNDCLASSA wc = {0}; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.lpszClassName = "SlideCombine"; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); RegisterClassA(&wc); HWND hwnd = CreateWindowExA(0, "SlideCombine", "PDF书签合并工具 v2.0", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 600, 500, NULL, NULL, hInstance, NULL); if (!hwnd) return 1; ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; }