From fbc39dc14dd0e739364a31028d11c8f18e654006 Mon Sep 17 00:00:00 2001 From: GuoJiKun Date: Mon, 6 Jan 2025 16:26:07 +0800 Subject: [PATCH 1/4] =?UTF-8?q?ci:=20=E5=A2=9E=E5=8A=A0=20PR=20=E5=92=8C?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E6=8E=A8=E9=80=81=E5=88=B0=E4=B8=BB=E5=88=86?= =?UTF-8?q?=E6=94=AF=E6=97=B6=E5=A2=9E=E5=8A=A0=20TS=20=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E6=A3=80=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/check-ts-type.yml | 28 ++++++++++++++++++++++++++++ README.md | 5 +++-- 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/check-ts-type.yml diff --git a/.github/workflows/check-ts-type.yml b/.github/workflows/check-ts-type.yml new file mode 100644 index 0000000..cfe57de --- /dev/null +++ b/.github/workflows/check-ts-type.yml @@ -0,0 +1,28 @@ +name: Typescript Check + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + check-ts-type: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: setup node + uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 9.12.3 + - name: Install frontend dependencies + run: pnpm install + - name: Check types + run: pnpm run type-check \ No newline at end of file diff --git a/README.md b/README.md index 62bc6a1..9d79759 100644 --- a/README.md +++ b/README.md @@ -58,11 +58,12 @@ pnpm tauri build - [x] ods - [x] csv - [x] docx - - 代码文件(utf8): + - 文本文件(utf8): - [x] html - [x] css - [x] js - [x] ts + - [x] tsx - [x] c - [x] cpp - [x] rs @@ -81,7 +82,7 @@ pnpm tauri build - [ ] rar - [ ] 7z - 设置 - - [ ] 支持格式的选择 + - [x] 支持格式的显示 - [ ] 版本显示以及更新 - [ ] 自启动 From 6efd7fe9ce80579d415b7c777b16bb37c6bb1b83 Mon Sep 17 00:00:00 2001 From: GuoJiKun Date: Mon, 6 Jan 2025 17:17:48 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=BC=A9=E6=94=BE?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src-tauri/Cargo.lock | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/src/helper/mod.rs | 2 +- src-tauri/src/preview.rs | 2 ++ src-tauri/tauri.conf.json | 2 +- 6 files changed, 7 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 70038ab..53ccfee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "quicklook", - "version": "0.8.0", + "version": "0.8.1", "description": "Windows 平台的文件预览工具", "private": true, "type": "module", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 7fa897d..4d0428e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -121,7 +121,7 @@ checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "app" -version = "0.8.0" +version = "0.8.1" dependencies = [ "calamine", "chrono", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 48cb665..53d0d5e 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "app" -version = "0.8.0" +version = "0.8.1" description = "Windows 平台的文件预览工具" authors = ["GuoJikun "] license = "" diff --git a/src-tauri/src/helper/mod.rs b/src-tauri/src/helper/mod.rs index e22b2e9..303f1ab 100644 --- a/src-tauri/src/helper/mod.rs +++ b/src-tauri/src/helper/mod.rs @@ -24,5 +24,5 @@ pub fn get_webview_window( } pub fn get_scaled_size(size: f64, scale: f64) -> f64 { - size * scale + size / scale } diff --git a/src-tauri/src/preview.rs b/src-tauri/src/preview.rs index b59c7dd..7952797 100644 --- a/src-tauri/src/preview.rs +++ b/src-tauri/src/preview.rs @@ -479,6 +479,7 @@ impl PreviewFile { let monitor_info = monitor::get_monitor_info(); let scale = monitor_info.scale; + println!("scale: {}", scale); let mut width = 1000.0; let mut height = 600.0; @@ -489,6 +490,7 @@ impl PreviewFile { log::info!("tmp_width: {}, tmo_height: {}", tmp_width, tmo_height); width = helper::get_scaled_size(tmp_width, scale); height = helper::get_scaled_size(tmo_height, scale); + } match app.get_webview_window("preview") { diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index dc9d59f..60859e9 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", "productName": "quicklook", - "version": "0.8.0", + "version": "0.8.1", "identifier": "dev.jikun.quicklook", "build": { "frontendDist": "../dist", From cab0278d27b5a32585a7807cb2f6ef51593b9d24 Mon Sep 17 00:00:00 2001 From: GuoJiKun Date: Tue, 7 Jan 2025 11:26:56 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E5=90=8E=E7=AC=AC=E4=B8=80=E6=AC=A1=E5=9C=A8?= =?UTF-8?q?=E6=A1=8C=E9=9D=A2=E9=A2=84=E8=A7=88Com=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E9=87=8A=E6=94=BE=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/src/preview.rs | 262 +++++++++++++++++++++------------------ 1 file changed, 141 insertions(+), 121 deletions(-) diff --git a/src-tauri/src/preview.rs b/src-tauri/src/preview.rs index 7952797..5d51621 100644 --- a/src-tauri/src/preview.rs +++ b/src-tauri/src/preview.rs @@ -18,7 +18,7 @@ use windows::{ Accessibility::{CUIAutomation, IUIAutomation, IUIAutomationSelectionPattern, UIA_NamePropertyId, UIA_SelectionPatternId}, Input::KeyboardAndMouse, Shell::{ - IShellBrowser, IShellItemArray, IShellView, IShellWindows, ShellWindows, SIGDN_DESKTOPABSOLUTEPARSING, SIGDN_FILESYSPATH, SVGIO_SELECTION, SWFO_NEEDDISPATCH + IShellBrowser, IShellItemArray, IShellView, IShellWindows, ShellWindows, SIGDN_DESKTOPABSOLUTEPARSING, SIGDN_FILESYSPATH, SVGIO_SELECTION, SWC_DESKTOP, SWFO_NEEDDISPATCH }, WindowsAndMessaging }, @@ -39,164 +39,171 @@ pub struct PreviewFile { app_handle: Option, } +#[derive(Debug)] +pub enum FwWindowType { + Explorer, + Desktop, + Dialog, +} + struct Selected; impl Selected { - pub fn new() -> Option { - let path = Self::get_selected_file(); - println!("path: {:?}", path); - return path; + pub fn new() -> Result { + match Self::get_selected_file() { + Ok(path) => Ok(path), + Err(e) => { + log::error!("Error: {:?}", e); + Err(e) + }, + } } - fn get_selected_file() -> Option { - if let Some(focused_type) = Self::get_focused_type() { - return match focused_type.as_str() { - "explorer" => unsafe { Self::get_select_file_from_explorer().ok() }, - "desktop" => unsafe { Self::get_select_file_from_desktop().ok() }, - "dialog" => { - match Self::get_select_file_from_dialog() { - Ok(result) => Some(result), - Err(err) => None - } - }, - _ => None, - }; + fn get_selected_file() -> Result { + if let Some(fw_window_type) = Self::get_focused_type() { + match fw_window_type { + FwWindowType::Explorer => unsafe { Self::get_selected_file_from_explorer() }, + FwWindowType::Desktop => unsafe { Self::get_selected_file_from_desktop() }, + FwWindowType::Dialog => Self::get_selected_file_from_dialog(), + } + } else { + Err(WError::from_win32()) } - None + + } - fn get_focused_type() -> Option { - let mut type_str: Option = None; + fn get_focused_type() -> Option { + let mut type_str: Option = None; let hwnd_gfw = unsafe { WindowsAndMessaging::GetForegroundWindow() }; let class_name = win::get_window_class_name(hwnd_gfw); log::info!("class_name: {}", class_name); if class_name.contains("CabinetWClass") { - type_str = Some("explorer".to_string()); + type_str = Some(FwWindowType::Explorer); } else if class_name.contains("Progman") || class_name.contains("WorkerW") { let defview = unsafe { WindowsAndMessaging::FindWindowExW(hwnd_gfw, None, w!("SHELLDLL_DefView"), None) }; if defview.is_ok() { - type_str = Some("desktop".to_string()); + type_str = Some(FwWindowType::Desktop); } }else if class_name.contains("#32770") { - type_str = Some("dialog".to_string()); + type_str = Some(FwWindowType::Dialog); } log::info!("type_str: {:?}", type_str); type_str } - unsafe fn get_select_file_from_explorer() -> Result { + unsafe fn get_selected_file_from_explorer() -> Result { let (tx, rx) = mpsc::channel(); // 在新的线程中执行 COM 操作 thread::spawn(move || { - // 在子线程中初始化 COM 库为单线程单元 - let _ = CoInitializeEx(None, COINIT_APARTMENTTHREADED); + let result: Result = (|| -> Result { + // 在子线程中初始化 COM 库为单线程单元 + let _ = CoInitializeEx(None, COINIT_APARTMENTTHREADED); - let hwnd_gfw = WindowsAndMessaging::GetForegroundWindow(); - let shell_windows: IShellWindows = - CoCreateInstance(&ShellWindows, None, CLSCTX_LOCAL_SERVER).unwrap(); - let result_hwnd = - WindowsAndMessaging::FindWindowExW(hwnd_gfw, None, w!("ShellTabWindowClass"), None) - .unwrap(); + let hwnd_gfw = WindowsAndMessaging::GetForegroundWindow(); + let shell_windows: IShellWindows = + CoCreateInstance(&ShellWindows, None, CLSCTX_LOCAL_SERVER)?; + let result_hwnd = + WindowsAndMessaging::FindWindowExW(hwnd_gfw, None, w!("ShellTabWindowClass"), None)?; - let mut target_path = String::new(); - let count = shell_windows.Count().unwrap_or_default(); + let mut target_path = String::new(); + let count = shell_windows.Count().unwrap_or_default(); - for i in 0..count { - let variant = VARIANT::from(i); - let dispatch: IDispatch = shell_windows.Item(&variant).unwrap(); + for i in 0..count { + let variant = VARIANT::from(i); + let dispatch: IDispatch = shell_windows.Item(&variant)?; - let shell_browser = Self::dispath2browser(dispatch); + let shell_browser = Self::dispath2browser(dispatch); - if shell_browser.is_none() { - continue; - } - let shell_browser = shell_browser.unwrap(); - // 调用 GetWindow 可能会阻塞 GUI 消息 - let phwnd = shell_browser.GetWindow().unwrap(); - if hwnd_gfw.0 != phwnd.0 && result_hwnd.0 != phwnd.0 { - continue; - } + if shell_browser.is_none() { + continue; + } + let shell_browser = shell_browser.unwrap(); + // 调用 GetWindow 可能会阻塞 GUI 消息 + let phwnd = shell_browser.GetWindow()?; + if hwnd_gfw.0 != phwnd.0 && result_hwnd.0 != phwnd.0 { + continue; + } - let shell_view = shell_browser.QueryActiveShellView().unwrap(); - target_path = Self::get_selected_file_path_from_shellview(shell_view); - } + let shell_view = shell_browser.QueryActiveShellView().unwrap(); + target_path = Self::get_selected_file_path_from_shellview(shell_view); + } - CoUninitialize(); - tx.send(target_path).unwrap(); + Ok(target_path) + + })(); + tx.send(result).unwrap(); + }); - - let target_path = rx.recv().unwrap(); + let target_path = rx.recv().unwrap()?; Ok(target_path) } - unsafe fn get_select_file_from_desktop() -> Result { + unsafe fn get_selected_file_from_desktop() -> Result { let (tx, rx) = mpsc::channel(); // 在新的线程中执行 COM 操作 thread::spawn(move || { - // 初始化 COM 库 - let _ = CoInitializeEx(None, COINIT_APARTMENTTHREADED); - let mut target_path = String::new(); - let hwnd_gfw = WindowsAndMessaging::GetForegroundWindow(); // 获取当前活动窗口句柄 - log::info!("hwnd_gfw: {:?}", hwnd_gfw); - let shell_windows: Result = - CoCreateInstance(&ShellWindows, None, CLSCTX_LOCAL_SERVER); - if shell_windows.is_err() { - log::info!("shell_windows 不存在"); - tx.send(target_path.clone()).unwrap(); - } - let shell_windows = shell_windows.unwrap(); - - let pvar_loc: VARIANT = Variant::VariantInit(); - - // 获取活动窗口 - let mut phwnd: i32 = 0; - - let dispatch = shell_windows - .FindWindowSW( - &pvar_loc, - &pvar_loc, - windows::Win32::UI::Shell::SWC_DESKTOP, - &mut phwnd, - SWFO_NEEDDISPATCH, - ); - if dispatch.is_err() { - log::info!("dispatch 不存在"); - tx.send(target_path.clone()).unwrap(); - } + let result: Result = (|| -> Result { + // 初始化 COM 库 + let _ = CoInitializeEx(None, COINIT_APARTMENTTHREADED); + + let mut target_path = String::new(); + let hwnd_gfw = WindowsAndMessaging::GetForegroundWindow(); // 获取当前活动窗口句柄 + log::info!("hwnd_gfw: {:?}", hwnd_gfw); + let shell_windows: Result = + CoCreateInstance(&ShellWindows, None, CLSCTX_LOCAL_SERVER); + if shell_windows.is_err() { + log::info!("shell_windows 不存在"); + return Ok(target_path); + } + let shell_windows = shell_windows?; - let shell_browser = Self::dispath2browser(dispatch.unwrap()); - if shell_browser.is_none() { - log::info!("shell_browser 不存在"); - tx.send(target_path.clone()).unwrap(); - } - let shell_browser = shell_browser.unwrap(); + let pvar_loc: VARIANT = Variant::VariantInit(); - let phwnd = shell_browser.GetWindow().unwrap(); - let top = WindowsAndMessaging::GetAncestor(phwnd, WindowsAndMessaging::GA_ROOT); + // 获取活动窗口 + let mut phwnd: i32 = 0; - if !hwnd_gfw.eq(&top) { - log::info!("top hwnd 不相等"); - tx.send(target_path.clone()).unwrap(); - } + let dispatch = shell_windows.FindWindowSW( + &pvar_loc, + &pvar_loc, + SWC_DESKTOP, + &mut phwnd, + SWFO_NEEDDISPATCH, + )?; - let shell_view = shell_browser.QueryActiveShellView(); - if shell_view.is_err() { - log::info!("shell_view 不存在"); - tx.send(target_path.clone()).unwrap(); - } + let shell_browser = Self::dispath2browser(dispatch); + if shell_browser.is_none() { + log::info!("shell_browser 不存在"); + return Ok(target_path); + } + + let shell_browser = shell_browser.unwrap(); + + let phwnd = shell_browser.GetWindow().unwrap(); + let top = WindowsAndMessaging::GetAncestor(phwnd, WindowsAndMessaging::GA_ROOT); - target_path = Self::get_selected_file_path_from_shellview(shell_view.unwrap()); - CoUninitialize(); - tx.send(target_path).unwrap(); + if hwnd_gfw.0 != top.0 { + log::info!("top hwnd 不相等"); + return Ok(target_path); + } + + let shell_view = shell_browser.QueryActiveShellView()?; + + target_path = Self::get_selected_file_path_from_shellview(shell_view); + + Ok(target_path) + })(); + tx.send(result).unwrap(); }); - let target_path = rx.recv().unwrap(); + + let target_path = rx.recv().unwrap()?; Ok(target_path) } - fn get_select_file_from_dialog() -> Result { + fn get_selected_file_from_dialog() -> Result { let mut target_path = String::new(); let fw_hwnd = unsafe { WindowsAndMessaging::GetForegroundWindow() @@ -222,7 +229,7 @@ impl Selected { log::info!("listview(DirectUIHWND) 不存在"); return Ok(target_path); } - let listview = listview.unwrap(); + let listview = listview?; let seleced_file_title = unsafe { let _ = CoInitializeEx(None, COINIT_APARTMENTTHREADED); // 通过 ui automation 获取选中文件 @@ -343,15 +350,27 @@ impl Selected { } } - if let Ok(display_name) = shell_item.GetDisplayName(SIGDN_FILESYSPATH) { - target_path = display_name.to_string().unwrap(); - break; - } if let Ok(display_name) = shell_item.GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING) { - target_path = display_name.to_string().unwrap(); + let tmp = display_name.to_string(); + if tmp.is_err() { + continue; + } + target_path = tmp.unwrap(); break; } + + if let Ok(display_name) = shell_item.GetDisplayName(SIGDN_FILESYSPATH) { + println!("display_name: {:?}", display_name); + let tmp = display_name.to_string(); + if tmp.is_err() { + println!("display_name error: {:?}", tmp.err()); + continue; + } + target_path = tmp.unwrap(); + break; + } + } target_path } @@ -439,7 +458,10 @@ impl PreviewFile { // 按键处理逻辑 pub fn handle_key_down(&self, vk_code: u32) { if vk_code == KeyboardAndMouse::VK_SPACE.0 as u32 { - let _ = Self::preview_file(self.app_handle.clone().unwrap()); + let result = Self::preview_file(self.app_handle.clone().unwrap()); + if result.is_err() { + log::error!("Error: {:?}", result.err().unwrap()); + } } } @@ -467,7 +489,7 @@ impl PreviewFile { pub fn preview_file(app: AppHandle) -> Result<(), TauriError> { let file_path = Selected::new(); - if file_path.is_some() { + if file_path.is_ok() { let file_path = file_path.unwrap(); let file_info = get_file_info(&file_path); @@ -479,19 +501,15 @@ impl PreviewFile { let monitor_info = monitor::get_monitor_info(); let scale = monitor_info.scale; - println!("scale: {}", scale); - let mut width = 1000.0; let mut height = 600.0; - if monitor_info.width > 0.0 { let tmp_width = monitor_info.width * 0.8; let tmo_height = monitor_info.height * 0.8; - log::info!("tmp_width: {}, tmo_height: {}", tmp_width, tmo_height); width = helper::get_scaled_size(tmp_width, scale); height = helper::get_scaled_size(tmo_height, scale); - } + log::info!("Client Rect: width - {}, height - : {}, scale - {}", width, height, scale); match app.get_webview_window("preview") { Some(window) => { @@ -548,6 +566,8 @@ impl PreviewFile { } } } + } else { + log::error!("Error: {:?}", file_path.err().unwrap()); } Ok(()) From 467ea48eda78e854a02fb1f32cc604025e8dd8c7 Mon Sep 17 00:00:00 2001 From: GuoJiKun Date: Tue, 7 Jan 2025 14:43:28 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=9C=A8=E5=BC=B9?= =?UTF-8?q?=E7=AA=97=E4=B8=AD=E9=A2=84=E8=A7=88=E6=96=87=E4=BB=B6=E6=97=B6?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E9=A2=84=E8=A7=88=E5=BA=93=E4=B8=8B=E9=9D=A2?= =?UTF-8?q?=E7=9A=84=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/src/preview.rs | 64 +++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/src-tauri/src/preview.rs b/src-tauri/src/preview.rs index 5d51621..f8a7037 100644 --- a/src-tauri/src/preview.rs +++ b/src-tauri/src/preview.rs @@ -1,24 +1,25 @@ use std::sync::mpsc; use std::thread; +use log::kv::ToValue; use tauri::{ webview::PageLoadEvent, AppHandle, Error as TauriError, Manager, WebviewUrl, WebviewWindowBuilder }; use windows::{ - core::{w, Error as WError, Interface, VARIANT}, + core::{w, Error as WError, Interface, HSTRING, VARIANT}, Win32::{ Foundation::{BOOL, HWND, LPARAM, LRESULT, WPARAM}, System::{ Com::{ CoCreateInstance, CoInitializeEx, CoUninitialize, IDispatch, IServiceProvider, CLSCTX_INPROC_SERVER, CLSCTX_LOCAL_SERVER, COINIT_APARTMENTTHREADED }, - SystemServices::SFGAO_FILESYSTEM, + SystemServices::{SFGAO_BROWSABLE, SFGAO_FILESYSTEM, SFGAO_FOLDER, SFGAO_STORAGE}, Variant::{self} }, UI::{ Accessibility::{CUIAutomation, IUIAutomation, IUIAutomationSelectionPattern, UIA_NamePropertyId, UIA_SelectionPatternId}, Input::KeyboardAndMouse, Shell::{ - IShellBrowser, IShellItemArray, IShellView, IShellWindows, ShellWindows, SIGDN_DESKTOPABSOLUTEPARSING, SIGDN_FILESYSPATH, SVGIO_SELECTION, SWC_DESKTOP, SWFO_NEEDDISPATCH + FOLDERID_Documents, FOLDERID_Downloads, FOLDERID_Libraries, FOLDERID_Music, FOLDERID_Pictures, FOLDERID_Videos, IShellBrowser, IShellItem, IShellItemArray, IShellView, IShellWindows, SHCreateItemFromParsingName, SHGetKnownFolderPath, ShellWindows, KF_FLAG_DEFAULT, SIGDN_DESKTOPABSOLUTEPARSING, SIGDN_FILESYSPATH, SIGDN_NORMALDISPLAY, SVGIO_SELECTION, SWC_DESKTOP, SWFO_NEEDDISPATCH }, WindowsAndMessaging }, @@ -279,16 +280,65 @@ impl Selected { let breadcrumb_hwnd = breadcrumb_hwnd.unwrap(); let mut breadcrumb_title = win::get_window_text(breadcrumb_hwnd); println!("breadcrumb_title: {:?}", breadcrumb_title); - let re = regex::Regex::new(r"[A-Z]:\\.*").unwrap(); - if let Some(cap) = re.find(&breadcrumb_title) { - breadcrumb_title = cap.as_str().to_string(); + let arr = breadcrumb_title.split(": ").map(|item|item.to_string()).collect::>(); + if arr.len() > 1 { + breadcrumb_title = arr[1].clone(); + } + + if !breadcrumb_title.contains(":\\") { + let path = Self::get_library_path(&breadcrumb_title); + println!("path: {:?}", path); + if path.is_err() { + return Ok(target_path); + } + breadcrumb_title = path.unwrap(); } target_path = format!("{}\\{}", breadcrumb_title, seleced_file_title); println!("target_path: {:?}", target_path); - + Ok(target_path) } + fn get_library_path(name: &str) -> Result { + unsafe { + // 1. 获取库文件夹路径 + let folder_id = match name { + "下载" => &FOLDERID_Downloads, + "音乐" => &FOLDERID_Music, + "图片" => &FOLDERID_Pictures, + "文档" => &FOLDERID_Documents, + "视频" => &FOLDERID_Videos, + "桌面" => &FOLDERID_Libraries, + _ => { + // 如果是自定义库,尝试从Libraries文件夹读取 + let libraries_path = SHGetKnownFolderPath( + &FOLDERID_Libraries, + KF_FLAG_DEFAULT, + None + )?; + + let lib_file = format!("{}\\{}.library-ms", libraries_path.to_string()?, name); + let shell_item: IShellItem = SHCreateItemFromParsingName( + &HSTRING::from(lib_file), + None + )?; + + return Ok(shell_item.GetDisplayName(SIGDN_FILESYSPATH)?.to_string()?); + } + }; + + println!("libraries_path: {:?}", folder_id); + + + let path = SHGetKnownFolderPath( + folder_id, + KF_FLAG_DEFAULT, + None + )?; + Ok(path.to_string()?) + } + + } unsafe extern "system" fn dialog_defview_proc(hwnd: HWND, lparam: LPARAM) -> BOOL { let list_view = lparam.0 as *mut Option;